npm package: @ianicdev/dataforms
Description: ```sh npm install --save @ianicdev/dataforms ```
Latest version: 0.19.5

## Installation

#### With NPM:

```sh
npm install --save @ianicdev/dataforms
```

#### With Yarn:

```sh
yarn add @ianicdev/dataforms
```

#### Inside main.js

```js
import Dataforms from "dataforms";
import { extend } from "vee-validate";
import * as rules from "vee-validate/dist/rules";

Vue.use(Dataforms);

Object.keys(rules).forEach((rule) => {
  extend(rule, rules[rule]);
});
```

---

## Intro

All the components must have some generic props such as label. The component structure is made of three parts:

1. type (ref: Components)
2. options (ref: Components Options)
3. \_validation
4. \_responsive

Feel free to use any component attributes you should use on vuetify components (such as dark theme, label, hints etc...)
**Hint**: All the generic props that start with underscore (\_) are special attributes and doesnt apply to the component. Its used from the library

##### Validation

All available validation rules can be found at https://vee-validate.logaretm.com/v3/guide/rules.html#rules.
A custom validation callback is provided from the library using the \_callback property

```js
validation: {
    _callback() => {
        return {
            validate: (value) => {
                console.log(value);
                return true;
            },
            message: "{_field_} is not valid(?)",
        }
    }
}
```

### Responsive

You can specify the grid system via the responsive properties

```js
_responsive: {
  sm: 12,
  md: 6,
  lg: 4,
},
```

### Generic options

`label: "I am a label"`
`hint: "Write something dude!",`
`"persistent-hint": true,`

### Components

**1. textField (default)**
**2. textArea**
**3. checkBoxes**
**4. radioButtons**
**5. fileInput**
**6. selects**
**7. selectsAutocomplete**

### 1. textField (default)

Basic text field

```js
name: {
  options: {
    label: "First name",
    hint: "Είσαι ο;",
    "persistent-hint": true,
  },
  validation: {
    required: true,
  },
},
```

### 2. textArea

Same with text field, a basic textarea component with validation

```js
 message: {
      type: "textArea",
      options: {
        label: "Write your message...",
        hint: "Write something dude!",
        "persistent-hint": true,
      },
      validation: {
        min: 3,
        max: 200,
      },
},
```

### 3. checkBoxes

This component requires an **items** array with the available options. Also you can set a default value (optional).

```js
terms: {
  type: "checkBoxes",
      options: {
        label: "Terms & conditions",
        default: "steal",
        hint: "write something here too!",
        "persistent-hint": true,
        items: [
          {
            label: "I aggree to steal all my data!",
            value: "steal",
          },
        ],
      },
      validation: {
        required: true,
      },
},
```

### 4. Radio

Radio selects msut have a **list** property (array) with the available values. You can also provide a default (optional) value

```js
website: {
  type: "radioButtons",
  options: {
    label: "What the of website do you need?",
    default: "web_development",
    list: [
      {
        label: "Web design",
        value: "web_design",
      },
      {
        label: "Web development",
        value: "web_development",
      },
      {
        label: "Logo Design",
        value: "logo_design",
      },
      "Other",
    ],
  },
}
```

### 5. fileInput (not tested)

This input acts like normal file input (you should notice the multiple, counter and show-size params) but there are some special rules at validation like **mimes** or **dimensions**

```js
yourImage: {
  type: "fileInput",
  options: {
    hint: "write something here too!",
    "persistent-hint": true,
    label: "Select your image...",
    counter: true,
    multiple: true,
    "show-size": true,
  },
  validation: {
    required: true,
    mimes: "image/*",
  },
}
```

### 6. selects

```js
deadline: {
  type: "selects",
  options: {
    label: "When do you need this project?",
    default: "web_development",
    items: [
      {
        text: "In 1 - 2 Months",
        value: "normal_client",
      },
      {
        text: "Now!",
        value: "now",
      },
      {
        text: "Yesterday!!!",
        value: "yesterday",
      },
    ],
  },
},
```

### 7.1 selectsAutocomplete (with Items)

It behaves like a normal select but you can search inside the list

```js
autocomplete: {
  type: "selectsAutocomplete",
  options: {
    label: "Autocomplete from list",
    default: "web_development",
    items: [
      {
        text: "In 1 - 2 Months",
        value: "normal_client",
      },
      {
        text: "Now!",
        value: "now",
      },
      {
        text: "Yesterday!!!",
        value: "yesterday",
      },
    ],
  },
  validation: {
    required: true,
  },
},
```

### 7.2 selectsAutocomplete (fetch Items from API - Once)

You should notice that this input doesnt have any **Items** property but it has an **apiUrl**. It will lazy load the Items.
The response should be an array of objects like the given below
**[{ text: 'Foo', value: 'Bar' }]**

```js
autocomplete: {
  type: "selectsAutocomplete",
  options: {
    label: "Autocomplete from api (fetch once)",
    default: "web_development",
    apiUrl: "https://api.publicapis.org/entries",
  },
  validation: {
    required: true,
  },
}
```

### 7.3 selectsAutocomplete (fetch Items from API - Live search)

You should notice the below properties

- **isSearchable**: enables the type-search feature
- **liveSearch**: enables the type-search feature
- **searchDelay**: time in ms that will wait before send the request (usefull when user is typing)

```js
autocomplete: {
  type: "selectsAutocomplete",
  options: {
    label: "Autocomplete from api (live fetching)",
    default: "web_development",
    apiUrl: "https://api.publicapis.org/entries",
    isSearchable: true,
    liveSearch: true,
    searchDelay: 300,
  },
  validation: {
    required: true,
  },
},
```

After the API Syntax, you should provide a submit property with a click function

```js
submit: {
  title: "Send Message",
  color: "primary",
  click: (formData) => {
    this.updateFormResult(formData);
    fetch("http://localhost:8080/api/test", requestOptions)
      .then((response) => response.json())
      .then((data) => console.log(data))
      .catch((err) => console.log(err));

    Object.keys(formData).forEach((formDataKey) => {
      body.append(formDataKey, formData[formDataKey]);
    });
    alert("Form sent!");
  },
},
```

### Basic example:

```js
<template>
  <v-app>
    <v-main>
      <v-container> <Form :api="api" /> </v-container>
      <v-container>
        <pre>{{ formResult }}</pre>
      </v-container>
    </v-main>
  </v-app>
</template>

<script>
import Form from "@/components/form.vue";
export default {
  name: "App",

  components: { Form },

  methods: {
    updateFormResult(formData) {
      this.formResult = formData;
    },
  },

  data() {
    return {
      formResult: {},
      api: {
        rows: [
          {
            input: [
              {
                name: {
                  options: {
                    label: "First name",
                    hint: "Είσαι ο;",
                    "persistent-hint": true,
                  },
                  validation: {
                    required: true,
                  },
                },
                email: {
                  options: {
                    default: "support@ianic.gr",
                    label: "Email",
                    prependIcon: "mdi-camera",
                  },
                  validation: {
                    required: true,
                    min: 4,
                    max: 24,
                    type: "email",
                    _callback: () => {
                      return {
                        validate: (value) => {
                          console.log(value);
                          return true;
                        },
                        message: "{_field_} is not valid(?)",
                      };
                    },
                  },
                  tooltip: {
                    position: "bottom",
                    text: "lorem ipsun",
                  },
                },
                _responsive: {
                  sm: 12,
                  md: 6,
                  lg: 4,
                },
              },
              {
                surname: {
                  options: {
                    readonly: true,
                    label: "Last name",
                  },
                },
                phone: {
                  options: {
                    loading: true,
                    label: "Phone",
                    hint: "Write 'hello' to proceed",
                    "persistent-hint": true,
                  },
                  validation: {
                    required: true,
                    is: "hello",
                  },
                  tooltip: {
                    text: "lorem ipsun",
                  },
                },
                _responsive: {
                  sm: 12,
                  md: 6,
                  lg: 4,
                },
              },
            ],
          },
          {
            input: [
              {
                deadline: {
                  type: "selects",
                  options: {
                    label: "When do you need this project?",
                    default: "web_development",
                    items: [
                      {
                        text: "In 1 - 2 Months",
                        value: "normal_client",
                      },
                      {
                        text: "Now!",
                        value: "now",
                      },
                      {
                        text: "Yesterday!!!",
                        value: "yesterday",
                      },
                    ],
                  },
                },
              },
              {
                autocomplete: {
                  type: "selectsAutocomplete",

                  options: {
                    label: "Autocomplete from list",
                    default: "web_development",
                    apiUrl: "https://api.publicapis.org/entries",
                    items: [
                      {
                        text: "In 1 - 2 Months",
                        value: "normal_client",
                      },
                      {
                        text: "Now!",
                        value: "now",
                      },
                      {
                        text: "Yesterday!!!",
                        value: "yesterday",
                      },
                    ],
                  },
                  validation: {
                    required: true,
                  },
                },
              },
            ],
          },
          {
            input: [
              {
                autocomplete: {
                  type: "selectsAutocomplete",

                  options: {
                    label: "Autocomplete from api (fetch once)",
                    default: "web_development",
                    apiUrl: "https://api.publicapis.org/entries",
                  },
                  validation: {
                    required: true,
                  },
                },
              },
              {
                autocomplete: {
                  type: "selectsAutocomplete",

                  options: {
                    label: "Autocomplete from api (live fetching)",
                    default: "web_development",
                    apiUrl: "https://api.publicapis.org/entries",
                    isSearchable: true,
                    liveSearch: true,
                    searchDelay: 300,
                  },
                  validation: {
                    required: true,
                  },
                },
              },
            ],
          },
          {
            input: [
              {
                website: {
                  responsive: {},
                  type: "radioButtons",
                  options: {
                    label: "What the of website do you need?",
                    default: "web_development",
                    list: [
                      {
                        label: "Web design",
                        value: "web_design",
                      },
                      {
                        label: "Web development",
                        value: "web_development",
                      },
                      {
                        label: "Logo Design",
                        value: "logo_design",
                      },
                      "Other",
                    ],
                  },
                },
              },
            ],
          },
          {
            input: [
              {
                message: {
                  type: "textArea",
                  options: {
                    label: "Write your message...",
                    hint: "Write something dude!",
                    "persistent-hint": true,
                  },
                  validation: {
                    min: 3,
                    max: 20,
                  },
                },
              },
            ],
          },
          {
            input: [
              {
                terms: {
                  type: "checkBoxes",
                  options: {
                    label: "Terms & conditions",
                    default: "steal",
                    hint: "write something here too!",
                    "persistent-hint": true,
                    items: [
                      {
                        label: "I aggree to steal all my data!",
                        value: "steal",
                      },
                    ],
                  },
                  validation: {
                    required: true,
                  },
                },
              },
            ],
          },
          {
            input: [
              {
                yourImage: {
                  type: "fileInput",
                  options: {
                    hint: "write something here too!",
                    "persistent-hint": true,
                    label: "Select your image...",
                    counter: true,
                    multiple: true,
                    "show-size": true,
                  },
                  validation: {
                    required: true,
                    mimes: "image/*",
                  },
                },
              },
            ],
          },
        ],
        submit: {
          title: "Send Message",
          color: "primary",
          click: (formData) => {
            this.updateFormResult(formData);

            /**
             * Post in general
             */

            const requestOptions = {
              method: "POST",
              headers: { "Content-Type": "multipart/form-data" },
              body: { ...formData },
            };

            fetch("http://localhost:8080/api/test", requestOptions)
              .then((response) => response.json())
              .then((data) => console.log("here", data))
              .catch((err) => console.log(err));

            /**
             *  Post the form with multipart/form-data or application/x-www-form-urlencoded;charset=UTF-8'
             *

            let body = new FormData();

            Object.keys(formData).forEach((formDataKey) => {
              body.append(formDataKey, formData[formDataKey]);
            });

            const requestOptions = {
              method: "POST",
              headers: { "Content-Type": "multipart/form-data" },
              body,
            };


            fetch("http://localhost:8080/api/test", requestOptions)
              .then((response) => response.json())
              .then((data) => console.log("here", data))
              .catch((err) => console.log(err));
            alert("Form sent!");
          },
          */

            alert("Form sent!");
          },
        },
      },
      value: "",
    };
  },
};
</script>
```