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