Skip to content
This repository was archived by the owner on Apr 9, 2025. It is now read-only.

Commit c60488b

Browse files
author
Daniel Requejo
committed
🦄 Added in-build validations
1 parent 8ed39cb commit c60488b

20 files changed

+332
-140
lines changed

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ export { default as FormHandler } from './FormHandler'
22
export { default as useFormHandler } from './useFormHandler'
33

44
export * from './core/constants'
5-
export * from './types/formHandler'
5+
export * from './types'

src/logic/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ export { default as getNativeFieldValue } from './getNativeFieldValue'
22
export { default as getDefaultFieldValue } from './getDefaultFieldValue'
33
export { default as validateField } from './validateField'
44
export { default as validateForm } from './validateForm'
5-
export { default as refFn } from './refFn'
5+
export { default as refFn } from './refFn'
6+
export { default as transformValidations } from './transformValidations'

src/logic/refFn.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Refs, FieldReference } from "../types/formHandler";
1+
import { Refs, FieldReference } from "../types";
22
import { isCheckboxInput, isMultipleSelect, isNativeControl, isRadioInput } from "../utils"
33

44
export default (name: string, _refs: Refs, values: any) => (fieldRef: any) => {
@@ -13,11 +13,11 @@ export default (name: string, _refs: Refs, values: any) => (fieldRef: any) => {
1313
}
1414
return
1515
}
16-
const isFirstRegister = !_refs[name].ref
16+
const isFirstRegister = _refs[name] && (!_refs[name].ref
1717
|| (Array.isArray(_refs[name].ref)
1818
&& isRadioInput(fieldRef)
1919
&& (!(_refs[name].ref as FieldReference[])
20-
.some((option: any) => option.value === fieldRef.value)))
20+
.some((option: any) => option.value === fieldRef.value))))
2121
if (isFirstRegister) {
2222
_refs[name].ref = isRadioInput(fieldRef)
2323
? [...(_refs[name].ref as FieldReference[] || [])

src/logic/transformValidations.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { ValidationsConfiguration, ValidationWithMessage, Validations } from "../types";
2+
import { max, maxLength, min, minLength, pattern, required } from "../utils";
3+
4+
export default (validations: ValidationsConfiguration = {}): Validations => {
5+
const transformed: Validations = {};
6+
if (!!validations.required) {
7+
transformed.required = typeof validations.required === 'string'
8+
? required(validations.required)
9+
: required();
10+
}
11+
if (validations.min) {
12+
transformed.min = typeof validations.min === 'number'
13+
? min(validations.min)
14+
: min(validations.min.value as number, validations.min.message);
15+
}
16+
if (validations.max) {
17+
transformed.max = typeof validations.max === 'number'
18+
? max(validations.max)
19+
: max(validations.max.value as number, validations.max.message);
20+
}
21+
if (validations.minLength) {
22+
transformed.minLength = typeof validations.minLength === 'number'
23+
? minLength(validations.minLength)
24+
: minLength(validations.minLength.value as number, validations.minLength.message);
25+
}
26+
if (validations.maxLength) {
27+
transformed.maxLength = typeof validations.maxLength === 'number'
28+
? maxLength(validations.maxLength)
29+
: maxLength(validations.maxLength.value as number, validations.maxLength.message);
30+
}
31+
if (validations.pattern) {
32+
transformed.pattern = !(validations.pattern as ValidationWithMessage)?.value
33+
? pattern(validations.pattern as RegExp)
34+
: pattern((validations.pattern as ValidationWithMessage).value as RegExp, (validations.pattern as ValidationWithMessage).message as string);
35+
}
36+
return transformed;
37+
}
38+

src/playground/App.vue

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,21 @@
22
<form @submit.prevent="() => handleSubmit(submitForm)">
33
<h2> VSSTS </h2>
44
<input v-bind="register('hello', {
5-
useNativeValidation: true,
6-
required: true,
5+
required: 'Something is required',
6+
pattern: /^[A-Za-z]+$/i
7+
})"><br>
8+
<input type="number" v-bind="register('hello2', {
9+
min: 5,
10+
max: 10
11+
})"><br>
12+
<input v-bind="register('hello3', {
13+
minLength: {
14+
value: 5,
15+
message: 'Min length is 5'
16+
},
17+
maxLength: 20,
18+
disabled: values.hello2 > 5
719
})"><br>
8-
<br>
9-
<input type="radio" value="male" v-bind="register('gender')"> Male<br>
10-
<input type="radio" value="female" v-bind="register('gender')"> Female<br>
11-
<input type="radio" value="other" v-bind="register('gender')"> Other<br>
1220
<br>
1321
<button>Submit</button>
1422
<pre>{{ values }}</pre>

src/types/baseControl.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/** Props for a base control */
2+
export interface BaseControlProps {
3+
/** Name of the control */
4+
name: string,
5+
6+
/** Current errors of the control */
7+
errors: string[]
8+
9+
/** Value binding for native inputs */
10+
ref: any,
11+
12+
/** Value binding for custom inputs */
13+
modelValue: any,
14+
15+
/** Handler binding for custom inputs */
16+
'onUpdate:modelValue': (value: any) => void,
17+
18+
/** Disabled state of the field*/
19+
disabled?: boolean
20+
21+
/** Current dirty state of the control */
22+
isDirty?: boolean
23+
24+
/** Current touched state of the control */
25+
isTouched?: boolean
26+
27+
/** Handler binding for native inputs */
28+
onChange?: (el: any) => void,
29+
30+
/** Blur handler */
31+
onBlur?: () => void,
32+
33+
/** Clear handler */
34+
onClear?: () => void,
35+
}
36+
37+
/** Each emit the handler could be expecting */
38+
export type EmitOption = 'update:modelValue' | 'blur' | 'clear'
39+
/** Emit collection for a base control */
40+
export type BaseControlEmits = EmitOption[]

src/types/formHandler.ts

Lines changed: 1 addition & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,4 @@
1-
export interface FieldReference {
2-
type: 'custom' | 'select' | 'select-multiple' | 'radio' | 'checkbox' | 'input' | 'textarea' | 'file' | 'range' | 'color' | 'date' | 'datetime-local' | 'email' | 'month' | 'number' | 'password' | 'search' | 'tel' | 'text' | 'time' | 'url' | 'week';
3-
value?: any;
4-
checked?: boolean;
5-
selected?: boolean;
6-
options?: any;
7-
nodeName?: string;
8-
}
9-
10-
export interface WrappedReference {
11-
ref: FieldReference | FieldReference[];
12-
_validations: Validations;
13-
_disabled: boolean;
14-
_defaultValue: any;
15-
}
16-
17-
export type Refs = Record<string, WrappedReference>;
18-
19-
/** Props for a base control */
20-
export interface BaseControlProps {
21-
/** Name of the control */
22-
name: string,
23-
24-
/** Current errors of the control */
25-
errors: string[]
26-
27-
/** Value binding for native inputs */
28-
ref: any,
29-
30-
/** Value binding for custom inputs */
31-
modelValue: any,
32-
33-
/** Handler binding for custom inputs */
34-
'onUpdate:modelValue': (value: any) => void,
35-
36-
/** Disabled state of the field*/
37-
disabled?: boolean
38-
39-
/** Current dirty state of the control */
40-
isDirty?: boolean
41-
42-
/** Current touched state of the control */
43-
isTouched?: boolean
44-
45-
/** Handler binding for native inputs */
46-
onChange?: (el: any) => void,
47-
48-
/** Blur handler */
49-
onBlur?: () => void,
50-
51-
/** Clear handler */
52-
onClear?: () => void,
53-
}
54-
55-
/** Each emit the handler could be expecting */
56-
export type EmitOption = 'update:modelValue' | 'blur' | 'clear'
57-
/** Emit collection for a base control */
58-
export type BaseControlEmits = EmitOption[]
1+
import { RegisterOptions, Register } from "./register"
592

603
export interface FormState {
614
/** Boolean holding the dirty state of the form */
@@ -77,59 +20,9 @@ export interface FormState {
7720
errors: Record<string, any>
7821
}
7922

80-
/** Function returning true for correct validation or a string with an error if it's invalid */
81-
export type ValidationFn = (_: any) => Promise<boolean | string> | boolean | string
82-
83-
/** Validations collection as an object */
84-
export type Validations = Record<string, ValidationFn>
85-
86-
export interface RegisterOptions {
87-
/** Indicates wether the input is native or not, set to false if the extra listeners are not desired */
88-
native?: boolean
89-
90-
/** Indicates wether the input is clearable or not */
91-
clearable?: boolean
92-
93-
/** Default value for the field */
94-
defaultValue?: any
95-
96-
/** Validations for the field */
97-
validations?: Validations
98-
99-
/** Set to true if you want to bind also dirty and touched states */
100-
withDetails?: boolean
101-
102-
/** Set to true if the field should be disabled */
103-
disabled?: boolean
104-
105-
/** Indicates if the control should use the native html validation */
106-
useNativeValidation?: boolean
107-
108-
/** Native required validation */
109-
required?: boolean
110-
111-
/** Native min validation */
112-
min?: number
113-
114-
/** Native max validation */
115-
max?: number
116-
117-
/** Native minLength validation */
118-
minLength?: number
119-
120-
/** Native maxLength validation */
121-
maxLength?: number
122-
123-
/** Native pattern validation */
124-
pattern?: string
125-
}
126-
12723
/** Field initializer */
12824
export type InitControl = (name: string, options: RegisterOptions) => void
12925

130-
/** Function that allows you to register a control to interact with the form */
131-
export type Register = (name: string, options?: RegisterOptions) => BaseControlProps
132-
13326
/** Sets dirty state of a control */
13427
export type SetDirty = (name: string, dirty: boolean) => void
13528

@@ -222,7 +115,6 @@ export interface FormHandlerParams {
222115
/** Validation behavior options */
223116
validationMode?: 'onChange' | 'onBlur' | 'onSubmit' | 'always'
224117
}
225-
226118
export interface FormHandlerReturn {
227119
/** Current form values */
228120
values: Record<string, any>

src/types/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export * from './formHandler'
2+
export * from './logic'
3+
export * from './register'
4+
export * from './validations'
5+
export * from './refs'
6+
export * from './baseControl'

src/types/logic.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { FormState, Refs, Validations } from "./formHandler"
1+
import { FormState } from "./formHandler"
2+
import { Refs } from "./refs"
23

34
export interface ValidateFormParams {
45
_refs: Refs

src/types/refs.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Validations } from "./register";
2+
3+
export interface FieldReference {
4+
type: 'custom' | 'select' | 'select-multiple' | 'radio' | 'checkbox' | 'input' | 'textarea' | 'file' | 'range' | 'color' | 'date' | 'datetime-local' | 'email' | 'month' | 'number' | 'password' | 'search' | 'tel' | 'text' | 'time' | 'url' | 'week';
5+
value?: any;
6+
checked?: boolean;
7+
selected?: boolean;
8+
options?: any;
9+
nodeName?: string;
10+
}
11+
12+
export interface WrappedReference {
13+
ref: FieldReference | FieldReference[];
14+
_validations: Validations;
15+
_disabled: boolean;
16+
_defaultValue: any;
17+
}
18+
19+
export type Refs = Record<string, WrappedReference>;

src/types/register.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { BaseControlProps } from "./baseControl";
2+
import { ValidationsConfiguration } from "./validations";
3+
4+
/** Function returning true for correct validation or a string with an error if it's invalid */
5+
export type ValidationFn = (_: any) => Promise<boolean | string> | boolean | string
6+
7+
/** Validations collection as an object */
8+
export type Validations = Record<string, ValidationFn>
9+
10+
11+
export interface RegisterOptions extends ValidationsConfiguration {
12+
/** Indicates wether the input is native or not, set to false if the extra listeners are not desired */
13+
native?: boolean
14+
15+
/** Indicates wether the input is clearable or not */
16+
clearable?: boolean
17+
18+
/** Default value for the field */
19+
defaultValue?: any
20+
21+
/** Validations for the field */
22+
validations?: Validations
23+
24+
/** Set to true if you want to bind also dirty and touched states */
25+
withDetails?: boolean
26+
27+
/** Set to true if the field should be disabled */
28+
disabled?: boolean
29+
30+
/** Indicates if the control should use the native html validation */
31+
useNativeValidation?: boolean
32+
}
33+
34+
/** Function that allows you to register a control to interact with the form */
35+
export type Register = (name: string, options?: RegisterOptions) => BaseControlProps

src/types/validations.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
export interface ValidationWithMessage {
2+
/** Validation value */
3+
value: number | string | RegExp
4+
5+
/** Validation message */
6+
message: string
7+
}
8+
9+
export interface ValidationsConfiguration {
10+
/** Required validation */
11+
/** If true, the field is required */
12+
/** If a string, the field is required and the string is the validation message */
13+
required?: boolean | string
14+
15+
/** Min validation */
16+
/** If a number, the field must be greater than or equal to the number */
17+
/** If an object, the field must be greater than or equal to the object.value and the object.message is the validation message */
18+
min?: number | ValidationWithMessage
19+
20+
/** Max validation */
21+
/** If a number, the field must be less than or equal to the number */
22+
/** If an object, the field must be less than or equal to the object.value and the object.message is the validation message */
23+
max?: number | ValidationWithMessage
24+
25+
/** MinLength validation */
26+
/** If a number, the field must be greater than or equal to the number */
27+
/** If an object, the field must be greater than or equal to the object.value and the object.message is the validation message */
28+
minLength?: number | ValidationWithMessage
29+
30+
/** MaxLength validation */
31+
/** If a number, the field must be less than or equal to the number */
32+
/** If an object, the field must be less than or equal to the object.value and the object.message is the validation message */
33+
maxLength?: number | ValidationWithMessage
34+
35+
/** Pattern validation */
36+
/** If a RegExp, the field must match the RegExp */
37+
/** If an object, the field must match the object.value and the object.message is the validation message */
38+
pattern?: RegExp | ValidationWithMessage
39+
}

0 commit comments

Comments
 (0)