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

Commit e04359f

Browse files
authored
Merge pull request #6 from dbssman/feature/1-gain-consistency-on-the-validation-strategy
Feature/1 gain consistency on the validation strategy
2 parents ccea41b + adc7a17 commit e04359f

29 files changed

+544
-260
lines changed

src/FormHandler.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import useFormHandler from './useFormHandler';
2-
import { FormHandlerParams, FormHandlerReturn } from './types';
2+
import { FormHandlerParams, FormHandlerReturn } from './types/formHandler';
33
import { defineComponent, PropType } from 'vue';
44

55
export default defineComponent({
@@ -8,15 +8,15 @@ export default defineComponent({
88
initialValues: Object as PropType<FormHandlerParams['initialValues']>,
99
interceptor: Function as PropType<FormHandlerParams['interceptor']>,
1010
validate: Function as PropType<FormHandlerParams['validate']>,
11-
options: Object as PropType<FormHandlerParams['options']>
11+
validationMode: Object as PropType<FormHandlerParams['validationMode']>
1212
},
13-
setup: (props, {slots}) => {
14-
const {...formHandler} = useFormHandler({
13+
setup: (props, { slots }) => {
14+
const { ...formHandler } = useFormHandler({
1515
initialValues: props.initialValues,
1616
interceptor: props.interceptor,
1717
validate: props.validate,
18-
options: props.options
18+
validationMode: props.validationMode
1919
})
20-
return () => slots.default && slots.default({...formHandler} as FormHandlerReturn)
20+
return () => slots.default && slots.default({ ...formHandler } as FormHandlerReturn)
2121
}
2222
})

src/constants.ts renamed to src/core/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { BaseControlEmits } from "./types"
1+
import { BaseControlEmits } from "../types"
22

33
export const DEFAULT_FIELD_VALUE = null;
44

src/index.ts

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

4-
export * from './constants'
4+
export * from './core/constants'
55
export * from './types'

src/logic/getDefaultFieldValue.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { isCheckboxInput } from "../utils"
2-
import { DEFAULT_FIELD_VALUE } from "../constants"
2+
import { DEFAULT_FIELD_VALUE } from "../core/constants"
33

44
export default (el: any) => {
55
if (!el) {

src/logic/getNativeFieldValue.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { DEFAULT_FIELD_VALUE } from './../constants';
1+
import { DEFAULT_FIELD_VALUE } from '../core/constants';
22
import { isCheckboxInput, isMultipleSelect, isRadioInput } from "../utils"
33

44
export default (el: any) => {

src/logic/index.ts

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

src/logic/refFn.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { Refs, FieldReference } from "../types";
2+
import { isCheckboxInput, isMultipleSelect, isNativeControl, isRadioInput } from "../utils"
3+
4+
export default (name: string, _refs: Refs, values: any) => (fieldRef: any) => {
5+
if (!fieldRef) {
6+
delete _refs[name]
7+
return
8+
}
9+
if (!fieldRef.nodeName || !isNativeControl(fieldRef)) {
10+
//TODO: Correctly type this in order to expect a fixed data structure
11+
_refs[name].ref = {
12+
type: 'custom'
13+
}
14+
return
15+
}
16+
const isFirstRegister = _refs[name] && (!_refs[name].ref
17+
|| (Array.isArray(_refs[name].ref)
18+
&& isRadioInput(fieldRef)
19+
&& (!(_refs[name].ref as FieldReference[])
20+
.some((option: any) => option.value === fieldRef.value))))
21+
if (isFirstRegister) {
22+
_refs[name].ref = isRadioInput(fieldRef)
23+
? [...(_refs[name].ref as FieldReference[] || [])
24+
, fieldRef]
25+
: fieldRef
26+
}
27+
if (isRadioInput(fieldRef)) {
28+
if (isFirstRegister && fieldRef.checked) {
29+
values[name] = fieldRef.value
30+
return
31+
}
32+
fieldRef.checked = (values[name] === fieldRef.value)
33+
return
34+
}
35+
if (isCheckboxInput(fieldRef)) {
36+
if (isFirstRegister) {
37+
values[name] = !!fieldRef.checked
38+
return
39+
}
40+
fieldRef.checked = !!values[name]
41+
return
42+
}
43+
if (isMultipleSelect(fieldRef)) {
44+
[...fieldRef.options].forEach((option: any, index) => {
45+
fieldRef[index].selected = !!values[name]?.includes(option.value)
46+
})
47+
return
48+
}
49+
fieldRef.value = values[name]
50+
};

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/logic/validateField.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { ValidateFieldParams } from './../types/logic';
2+
3+
export default async ({ name, values, formState, _refs }: ValidateFieldParams): Promise<void> => {
4+
if (!Object.keys(_refs[name]._validations).length) {
5+
return
6+
}
7+
if (_refs[name]._disabled) {
8+
return
9+
}
10+
for (const [validationName, validation] of Object.entries(_refs[name]._validations)) {
11+
const result = await validation(values[name])
12+
formState.errors[name] = {
13+
...(result !== true && { [validationName]: result })
14+
}
15+
if (result !== true) {
16+
break;
17+
}
18+
delete formState.errors[name]
19+
}
20+
}

src/logic/validateForm.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { ValidateFormParams } from './../types/logic';
2+
import validateField from "./validateField"
3+
4+
export default async (params: ValidateFormParams) => {
5+
for (const name of Object.keys(params.values)) {
6+
await validateField({ ...params, name })
7+
}
8+
}

src/playground/App.vue

Lines changed: 27 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,36 @@
11
<template>
2-
<h2> VSSTS </h2>
3-
<input v-bind="register('hello')"><br>
4-
<input type="number" v-bind="register('number')"><br>
5-
<input type="radio" value="female" name="test"> Female<br>
6-
<input type="radio" value="other" name="test"> Other<br>
7-
<br>
8-
<input type="radio" value="male" v-bind="register('gender')"> Male<br>
9-
<input type="radio" value="female" v-bind="register('gender')"> Female<br>
10-
<input type="radio" value="other" v-bind="register('gender')"> Other<br>
11-
<br>
12-
<input type="checkbox" v-bind="register('checkbox')"> Other <br>
13-
<br>
14-
<select v-bind="register('select1')" style="min-width:300px">
15-
<option value="">--- Please select option ---</option>
16-
<option value="dog">Dog</option>
17-
<option value="cat">Cat</option>
18-
<option value="hamster">Hamster</option>
19-
<option value="parrot">Parrot</option>
20-
<option value="spider">Spider</option>
21-
<option value="goldfish">Goldfish</option>
22-
</select><br>
23-
<br>
24-
<select v-bind="register('select')" style="min-width:300px" multiple>
25-
<option value="dog">Dog</option>
26-
<option value="cat">Cat</option>
27-
<option value="hamster">Hamster</option>
28-
<option value="parrot">Parrot</option>
29-
<option value="spider">Spider</option>
30-
<option value="goldfish">Goldfish</option>
31-
</select><br>
32-
<br>
33-
<textarea v-bind="register('textArea')"></textarea>
34-
<pre>{{ values }}</pre>
35-
<pre>{{ formState }}</pre>
36-
<pre>{{ modifiedValues() }}</pre>
37-
<template v-if="!!dynamic">
38-
<input v-bind="register('dynamic')"> <br>
39-
</template> <br>
40-
41-
42-
<button @click="setValue('gender', 'female')">Set radio to female</button>
43-
<button @click="setValue('select', ['dog', 'cat'])">Set select to dog & cat</button>
44-
<button @click="resetField('checkbox')">Reset checkbox</button>
45-
<button @click="dynamic = true">Add dynamic field</button>
2+
<form @submit.prevent="() => handleSubmit(submitForm)">
3+
<h2> VSSTS </h2>
4+
<input v-bind="register('hello', {
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
19+
})"><br>
20+
<br>
21+
<button>Submit</button>
22+
<pre>{{ values }}</pre>
23+
<pre>{{ formState }}</pre>
24+
</form>
4625
</template>
4726

4827
<script setup lang="ts">
4928
import useFormHandler from '../useFormHandler';
50-
import { ref } from 'vue'
51-
const dynamic = ref(false)
52-
53-
const { register, values, formState, resetField, setValue, modifiedValues } = useFormHandler({
54-
initialValues: {
55-
gender: 'male'
56-
}
57-
});
5829
30+
const { register, handleSubmit, values, formState } = useFormHandler({});
31+
const submitForm = (values: any) => {
32+
console.log(values)
33+
}
5934
</script>
6035

6136
<style>

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[]

0 commit comments

Comments
 (0)