|
1 |
| -# register |
| 1 | +# register |
| 2 | + |
| 3 | +Base logic for the functionality of the form handler, it takes a field name and an object as an **optional** argument, it returns the necessary handlers/props to be bound to our inputs. |
| 4 | + |
| 5 | +## Demo |
| 6 | + |
| 7 | +Coming soon... |
| 8 | + |
| 9 | +## Props |
| 10 | + |
| 11 | +| attribute | type | description | |
| 12 | +|-----------|-------------------|---------------------------------------| |
| 13 | +| name | `string` | Name for the field | |
| 14 | +| options | [RegisterOptions](/api/use-form-handler/register.html#type-declarations) | Optional configuration for the field | |
| 15 | + |
| 16 | +### `options` |
| 17 | + |
| 18 | +| attribute | type | description | |
| 19 | +|-----------|-------------------|---------------------------------------| |
| 20 | +| native | `boolean` | Explicitly indicates if the field is a native input or not. The main idea of this is to avoid binding the native input handler to custom components. | |
| 21 | +| defaultValue| `any` | Default value for the field, would override the fallback value when the field is empty/cleared | |
| 22 | +| validate | [Validations](/api/use-form-handler/register.html#type-declarations) | [Custom validations](/get-started/quick-start.html#custom-validation) object. | |
| 23 | +| withDetails | `boolean` | Explicitly indicates if you want to bind dirty and and touched state for the registered field | |
| 24 | +| disabled | `boolean` | Disables the field. When a field is disabled it gets reset, and is not able to validate, or set new values until it is enabled again. The field is also not considered for the form validation. | |
| 25 | +| useNativeValidation | `boolean` | Set to true if you want to use native HTML validation | |
| 26 | + |
| 27 | + |
| 28 | + |
| 29 | +## Return |
| 30 | + |
| 31 | +| attribute | type | description | |
| 32 | +|-----------|-------------------|---------------------------------------| |
| 33 | +| name | `string` | Name of the field | |
| 34 | +| error | <code>string | undefined</code> | Current error of the field | |
| 35 | +| ref | `(fieldRef:any) => void` | Takes care of updating and keeping the fields correctly aligned with the form, specially when talking about native inputs | |
| 36 | +| modelValue | `any` | Current field value binding for non-native inputs | |
| 37 | +| 'onUpdate:modelValue' | `(value: any) => Promise<void>` | Value update handler for non-native inputs | |
| 38 | +| onBlur | `() => void` | Blur handler | |
| 39 | +| onClear | `() => void` | Clear handler | |
| 40 | +| disabled | `boolean` | Disabled state binding for the field | |
| 41 | +| isDirty | `boolean` | Dirty state binding for the field. Only returned if `withDetails` is true | |
| 42 | +| isTouched | `boolean` | Touched state binding for the field. Only returned if `withDetails` is true | |
| 43 | +| onChange | `(el: any) => Promise<void>` | Value update handler for native inputs | |
| 44 | +| required | `boolean` | Native required validation. Only returned if `useNativeValidations` is set to true and `required` is set. | |
| 45 | +| min | `number` | Native min validation. Only returned if `useNativeValidations` is set to true and `min` is set. | |
| 46 | +| max | `number` | Native max validation. Only returned if `useNativeValidations` is set to true and `max` is set. | |
| 47 | +| minLength | `number` | Native minLength validation. Only returned if `useNativeValidations` is set to true and `minLength` is set. | |
| 48 | +| maxLength | `number` | Native maxLength validation. Only returned if `useNativeValidations` is set to true and `maxLength` is set. | |
| 49 | +| pattern | `RegExp` | Native pattern validation. Only returned if `useNativeValidations` is set to true and `pattern` is set. | |
| 50 | + |
| 51 | +:::info |
| 52 | +Notice how `modelValue` and `'onUpdate:modelValue'` are used as our two way data binding for non-native inputs following the Vue [approach](https://vuejs.org/guide/components/v-model.html). So that your fields used for complex forms could also be re-used in other parts of your application with v-model. |
| 53 | +::: |
| 54 | + |
| 55 | + |
| 56 | +## Usage |
| 57 | + |
| 58 | +### Basic |
| 59 | + |
| 60 | +```vue |
| 61 | +<template> |
| 62 | + <input type="text" v-bind="register('name')" /> |
| 63 | +</template> |
| 64 | +<script setup lang="ts" > |
| 65 | +import { useFormHandler } from 'vue-form-handler' |
| 66 | +const { register } = useFormHandler() |
| 67 | +</script> |
| 68 | +``` |
| 69 | + |
| 70 | +The usage is very simple and intuitive, we just get the `register` function from the handler and use it to attach our fields to the form, the most basic use case, just by giving it a name as above. Once the field is registered it is ready and interacts with the form without any more effort on our side. |
| 71 | + |
| 72 | +### Default value |
| 73 | + |
| 74 | +```vue |
| 75 | +<template> |
| 76 | + <select v-bind="register('country', { |
| 77 | + defaultValue: 'ESP' |
| 78 | + })" placeholder="Choose your country"> |
| 79 | + <option value="CAN">Canada</option> |
| 80 | + <option value="USA">United States</option> |
| 81 | + <option value="JAP">Japan</option> |
| 82 | + <option value="CHN">China</option> |
| 83 | + <option value="ESP">Spain</option> |
| 84 | + <option value="DEU">Germany</option> |
| 85 | + </select> |
| 86 | +</template> |
| 87 | +
|
| 88 | +<script setup lang="ts" > |
| 89 | +import { useFormHandler } from 'vue-form-handler' |
| 90 | +const { register } = useFormHandler() |
| 91 | +</script> |
| 92 | +``` |
| 93 | + |
| 94 | +As you can see, setting a default value for a field, in this case the country, is very simple, we just give it the value we want and it will be the `default`, not to confuse with the `initial` value, clearing the field will return it to it's default value, or to a value fallback if no default is specified. |
| 95 | + |
| 96 | +:::warning |
| 97 | +The handler supports also initialization via html attributes like `selected` or `checked` but it is highly recommended to just use the tools that are provided. |
| 98 | +::: |
| 99 | + |
| 100 | +### In-built Validation |
| 101 | + |
| 102 | +```vue |
| 103 | +<template> |
| 104 | + <form> |
| 105 | + <input type="email" v-bind="register('email', { |
| 106 | + required: true, |
| 107 | + pattern: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i |
| 108 | + })" /> |
| 109 | + <p v-show="formState.errors.email"> |
| 110 | + {{ formState.errors.email }} |
| 111 | + </p> |
| 112 | + <input type="number" v-bind="register('age', { |
| 113 | + min: 18, |
| 114 | + max: 50 |
| 115 | + })" /> |
| 116 | + <p v-show="formState.errors.age"> |
| 117 | + {{ formState.errors.age }} |
| 118 | + </p> |
| 119 | + <textarea v-bind="register('description', { |
| 120 | + minLength: 15, |
| 121 | + maxLength: 300, |
| 122 | + })" /> |
| 123 | + <p v-show="formState.errors.description"> |
| 124 | + {{ formState.errors.description }} |
| 125 | + </p> |
| 126 | + </form> |
| 127 | +</template> |
| 128 | +<script setup lang="ts" > |
| 129 | +import { useFormHandler } from 'vue-form-handler'; |
| 130 | +
|
| 131 | +const { register, formState } = useFormHandler(); |
| 132 | +</script> |
| 133 | +``` |
| 134 | + |
| 135 | +Quick an easy validate your fields by just passing a single attribute. The errors displayed will be very generic and also not maybe working for your locale, that's why we can customize the error message by passing the validation with a different interface. |
| 136 | + |
| 137 | +```vue{4-8} |
| 138 | +<template> |
| 139 | + <form> |
| 140 | + <input type="email" v-bind="register('email', { |
| 141 | + required: 'This is the required message', |
| 142 | + pattern: { |
| 143 | + value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, |
| 144 | + message: 'Pattern is failing' |
| 145 | + } |
| 146 | + })" /> |
| 147 | + <p v-show="formState.errors.email"> |
| 148 | + {{ formState.errors.email }} |
| 149 | + </p> |
| 150 | + ... |
| 151 | + </form> |
| 152 | +</template> |
| 153 | +<script setup lang="ts" > |
| 154 | +import { useFormHandler } from 'vue-form-handler'; |
| 155 | +
|
| 156 | +const { register, formState } = useFormHandler(); |
| 157 | +</script> |
| 158 | +``` |
| 159 | +The case of `required` is a bit special, you'll be able to get the custom message by just passing the string you wish. For the rest, they take an object as currently `pattern` does, with the `value` being the validation value, and `message` being the custom message to display. |
| 160 | + |
| 161 | +### Native validations |
| 162 | + |
| 163 | +You can also opt to let HTML validate your fields by passing `useNativeValidation` to true in the register options, i.e: |
| 164 | + |
| 165 | +```vue{4-6} |
| 166 | +<template> |
| 167 | + <form @submit.prevent="handleSubmit(successFn)"> |
| 168 | + <input type="email" v-bind="register('email', { |
| 169 | + required: true, |
| 170 | + pattern: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, |
| 171 | + useNativeValidation: true |
| 172 | + })" /> |
| 173 | + <p v-show="formState.errors.email"> |
| 174 | + {{ formState.errors.email }} |
| 175 | + </p> |
| 176 | + ... |
| 177 | + </form> |
| 178 | +</template> |
| 179 | +<script setup lang="ts" > |
| 180 | +import { useFormHandler } from 'vue-form-handler'; |
| 181 | +
|
| 182 | +const { register, formState, handleSubmit } = useFormHandler(); |
| 183 | +const successFn = (form:Record<string,any>) => {console.log({form})} |
| 184 | +</script> |
| 185 | +``` |
| 186 | +:::warning |
| 187 | +Please remember that you'll not be able to pass custom messages to native validations. |
| 188 | +::: |
| 189 | + |
| 190 | + |
| 191 | +### Custom validations |
| 192 | + |
| 193 | +```vue{13-15} |
| 194 | +<template> |
| 195 | + <form> |
| 196 | + <input type="password" v-bind="register('password', { |
| 197 | + required: true, |
| 198 | + pattern: passwordRegExp |
| 199 | + })" /> |
| 200 | + <p class="error" v-show="formState.errors.password"> |
| 201 | + {{ formState.errors.password }} |
| 202 | + </p> |
| 203 | + <input type="password" v-bind="register('confirmPassword', { |
| 204 | + required: true, |
| 205 | + pattern: passwordRegExp, |
| 206 | + validate: { |
| 207 | + match: (value) => value === values.password || 'Passwords do not match' |
| 208 | + } |
| 209 | + })" /> |
| 210 | + <p class="error" v-show="formState.errors.confirmPassword"> |
| 211 | + {{ formState.errors.confirmPassword }} |
| 212 | + </p> |
| 213 | + </form> |
| 214 | +</template> |
| 215 | +<script setup lang="ts" > |
| 216 | +import { useFormHandler } from 'vue-form-handler'; |
| 217 | +
|
| 218 | +const passwordRegExp = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/ |
| 219 | +const { values, register, formState } = useFormHandler({ validationMode: 'always' }); |
| 220 | +</script> |
| 221 | +``` |
| 222 | +Custom validations are kept very simple, can be synchronous or asynchronous. We just pass a function that will get executed when the field needs to be validated. It is expected that the function returns: `true` if the field is valid/ a `string` corresponding to the error due to the failing validation. |
| 223 | +## Type Declarations |
| 224 | + |
| 225 | +```ts |
| 226 | +export interface BaseControlProps { |
| 227 | + name: string, |
| 228 | + error: string, |
| 229 | + ref: any, |
| 230 | + modelValue: any, |
| 231 | + 'onUpdate:modelValue': (value: any) => Promise<void>, |
| 232 | + onBlur: () => void, |
| 233 | + onClear: () => void, |
| 234 | + disabled?: boolean |
| 235 | + isDirty?: boolean |
| 236 | + isTouched?: boolean |
| 237 | + onChange?: (el: any) => Promise<void>, |
| 238 | +} |
| 239 | + |
| 240 | +export type ValidationFn = ( |
| 241 | + value: any |
| 242 | +) => Promise<boolean | string> | boolean | string |
| 243 | + |
| 244 | +export type Validations = Record<string, ValidationFn> |
| 245 | + |
| 246 | +export interface ValidationWithMessage { |
| 247 | + value: number | string | RegExp |
| 248 | + message: string |
| 249 | +} |
| 250 | + |
| 251 | +export interface ValidationsConfiguration { |
| 252 | + required?: boolean | string |
| 253 | + min?: number | ValidationWithMessage |
| 254 | + max?: number | ValidationWithMessage |
| 255 | + minLength?: number | ValidationWithMessage |
| 256 | + maxLength?: number | ValidationWithMessage |
| 257 | + pattern?: RegExp | ValidationWithMessage |
| 258 | +} |
| 259 | + |
| 260 | +export interface RegisterOptions extends ValidationsConfiguration { |
| 261 | + native?: boolean |
| 262 | + defaultValue?: any |
| 263 | + validate?: Validations |
| 264 | + withDetails?: boolean |
| 265 | + disabled?: boolean |
| 266 | + useNativeValidation?: boolean |
| 267 | +} |
| 268 | + |
| 269 | +export type RegisterReturn = BaseControlProps & ValidationsConfiguration |
| 270 | + |
| 271 | +export type Register = ( |
| 272 | + name: string, |
| 273 | + options?: RegisterOptions |
| 274 | +) => RegisterReturn |
| 275 | +``` |
0 commit comments