1# Forms
2
3Forms are created using the [bootstrap-vue form
4component](https://bootstrap-vue.org/docs/components/form)
5and validated with the [Vuelidate](https://vuelidate.js.org/#sub-installation)
6plugin.
7
8## Form component
9
10When creating a new form, use the `<b-form>` [form
11component](https://bootstrap-vue.org/docs/components/form). Use the `.prevent`
12event modifier on submit to prevent the submit event from reloading the page.
13
14## Form group component
15
16The `<b-form-group>` [form group
17component](https://bootstrap-vue.org/docs/components/form-group)
18pairs form controls with a legend or label, helper text, invalid/valid
19feedback text, and visual validation state feedback. Learn more about
20commonly used form components:
21
22- [Form checkbox](https://bootstrap-vue.org/docs/components/form-checkbox)
23- [Form input](https://bootstrap-vue.org/docs/components/form-input)
24- [Form radio](https://bootstrap-vue.org/docs/components/form-radio)
25- [Form select](https://bootstrap-vue.org/docs/components/form-select)
26- [Form file custom component](/guide/components/file-upload)
27
28When helper text is provided, use the `<b-form-text>` component and `aria-describedby` on the
29form group component the helper text describes.
30
31## Validation
32
33For custom form validation messages, disable browser native HTML5
34validation by setting the `novalidate` prop on `<b-form>`. Use Vuelidate to
35check the form validation state and add
36custom validation messages in the `<b-form-invalid-feedback>` component.
37
38When creating a new form add the `VuelidateMixin`
39to the `scripts` block and import any
40[validators](https://vuelidate.js.org/#validators) needed
41such as: `required`, `requiredIf`, etc. The use of built-in validators is
42preferred.
43
44## Complete form
45
46A complete form will look like this.
47
48```vue
49<template>
50  <b-form novalidate @submit.prevent="handleSubmit">
51    <b-form-group
52      :label="$t('pageName.form.inputLabel')"
53      label-for="form-input-id"
54    >
55      <b-form-text id="form-input-helper-text">
56        {{ $t('pageName.form.helperText') }}
57      </b-form-text>
58      <b-form-input
59        id="form-input-id"
60        v-model="form.input"
61        type="text"
62        aria-describedby="form-input-helper-text"
63        :state="getValidationState($v.form.input)"
64        @change="$v.form.input.$touch()"
65      />
66      <b-form-invalid-feedback role="alert">
67        <div v-if="!$v.form.input.required">
68          {{ $t('global.form.fieldRequired') }}
69        </div>
70      </b-form-invalid-feedback>
71    </b-form-group>
72    <b-button variant="primary" type="submit" class="mb-3">
73      {{ $t('global.action.save') }}
74    </b-button>
75  </b-form>
76</template>
77
78<script>
79import VuelidateMixin from '@/components/Mixins/VuelidateMixin';
80import { required } from 'vuelidate/lib/validators';
81
82export default {
83  name: 'PageName',
84  components: {
85  ...
86  },
87  mixins: [VuelidateMixin],
88  data(){
89    form: {
90      input: '',
91    }
92  },
93  validations() {
94    return {
95      form: {
96        input: { required },
97      }
98    }
99  },
100  computed: {
101    ...
102  },
103  created() {
104    ...
105  },
106  methods:{
107    handleSubmit() {
108      this.$v.$touch();
109      if (this.$v.$invalid) return;
110      this.$store
111        .dispatch(
112          'pageName/updateFormData',
113          formData
114        )
115        .then((success) => {
116          this.successToast(success);
117        })
118        .catch(({ message }) => this.errorToast(message))
119        .finally(() => {
120          this.$v.form.$reset();
121          this.endLoader();
122        });
123    },
124};
125</script>
126```
127