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