diff --git a/src/FormHandler.ts b/src/FormHandler.ts index a056d79..abe26a0 100644 --- a/src/FormHandler.ts +++ b/src/FormHandler.ts @@ -1,5 +1,5 @@ import useFormHandler from './useFormHandler'; -import { FormHandlerParams, FormHandlerReturn } from './types'; +import { FormHandlerParams, FormHandlerReturn } from './types/formHandler'; import { defineComponent, PropType } from 'vue'; export default defineComponent({ @@ -8,15 +8,15 @@ export default defineComponent({ initialValues: Object as PropType, interceptor: Function as PropType, validate: Function as PropType, - options: Object as PropType + validationMode: Object as PropType }, - setup: (props, {slots}) => { - const {...formHandler} = useFormHandler({ + setup: (props, { slots }) => { + const { ...formHandler } = useFormHandler({ initialValues: props.initialValues, interceptor: props.interceptor, validate: props.validate, - options: props.options + validationMode: props.validationMode }) - return () => slots.default && slots.default({...formHandler} as FormHandlerReturn) + return () => slots.default && slots.default({ ...formHandler } as FormHandlerReturn) } }) \ No newline at end of file diff --git a/src/constants.ts b/src/core/constants.ts similarity index 93% rename from src/constants.ts rename to src/core/constants.ts index 6143919..897155e 100644 --- a/src/constants.ts +++ b/src/core/constants.ts @@ -1,4 +1,4 @@ -import { BaseControlEmits } from "./types" +import { BaseControlEmits } from "../types" export const DEFAULT_FIELD_VALUE = null; diff --git a/src/index.ts b/src/index.ts index cfd473d..5f60bb8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ export { default as FormHandler } from './FormHandler' export { default as useFormHandler } from './useFormHandler' -export * from './constants' +export * from './core/constants' export * from './types' \ No newline at end of file diff --git a/src/logic/getDefaultFieldValue.ts b/src/logic/getDefaultFieldValue.ts index e5aea9f..e53729c 100644 --- a/src/logic/getDefaultFieldValue.ts +++ b/src/logic/getDefaultFieldValue.ts @@ -1,5 +1,5 @@ import { isCheckboxInput } from "../utils" -import { DEFAULT_FIELD_VALUE } from "../constants" +import { DEFAULT_FIELD_VALUE } from "../core/constants" export default (el: any) => { if (!el) { diff --git a/src/logic/getNativeFieldValue.ts b/src/logic/getNativeFieldValue.ts index c5a1ded..c5ad313 100644 --- a/src/logic/getNativeFieldValue.ts +++ b/src/logic/getNativeFieldValue.ts @@ -1,4 +1,4 @@ -import { DEFAULT_FIELD_VALUE } from './../constants'; +import { DEFAULT_FIELD_VALUE } from '../core/constants'; import { isCheckboxInput, isMultipleSelect, isRadioInput } from "../utils" export default (el: any) => { diff --git a/src/logic/index.ts b/src/logic/index.ts index d1f1a03..45d83d2 100644 --- a/src/logic/index.ts +++ b/src/logic/index.ts @@ -1,2 +1,6 @@ export { default as getNativeFieldValue } from './getNativeFieldValue' -export { default as getDefaultFieldValue } from './getNativeFieldValue' \ No newline at end of file +export { default as getDefaultFieldValue } from './getDefaultFieldValue' +export { default as validateField } from './validateField' +export { default as validateForm } from './validateForm' +export { default as refFn } from './refFn' +export { default as transformValidations } from './transformValidations' \ No newline at end of file diff --git a/src/logic/refFn.ts b/src/logic/refFn.ts new file mode 100644 index 0000000..5718781 --- /dev/null +++ b/src/logic/refFn.ts @@ -0,0 +1,50 @@ +import { Refs, FieldReference } from "../types"; +import { isCheckboxInput, isMultipleSelect, isNativeControl, isRadioInput } from "../utils" + +export default (name: string, _refs: Refs, values: any) => (fieldRef: any) => { + if (!fieldRef) { + delete _refs[name] + return + } + if (!fieldRef.nodeName || !isNativeControl(fieldRef)) { + //TODO: Correctly type this in order to expect a fixed data structure + _refs[name].ref = { + type: 'custom' + } + return + } + const isFirstRegister = _refs[name] && (!_refs[name].ref + || (Array.isArray(_refs[name].ref) + && isRadioInput(fieldRef) + && (!(_refs[name].ref as FieldReference[]) + .some((option: any) => option.value === fieldRef.value)))) + if (isFirstRegister) { + _refs[name].ref = isRadioInput(fieldRef) + ? [...(_refs[name].ref as FieldReference[] || []) + , fieldRef] + : fieldRef + } + if (isRadioInput(fieldRef)) { + if (isFirstRegister && fieldRef.checked) { + values[name] = fieldRef.value + return + } + fieldRef.checked = (values[name] === fieldRef.value) + return + } + if (isCheckboxInput(fieldRef)) { + if (isFirstRegister) { + values[name] = !!fieldRef.checked + return + } + fieldRef.checked = !!values[name] + return + } + if (isMultipleSelect(fieldRef)) { + [...fieldRef.options].forEach((option: any, index) => { + fieldRef[index].selected = !!values[name]?.includes(option.value) + }) + return + } + fieldRef.value = values[name] +}; \ No newline at end of file diff --git a/src/logic/transformValidations.ts b/src/logic/transformValidations.ts new file mode 100644 index 0000000..a791104 --- /dev/null +++ b/src/logic/transformValidations.ts @@ -0,0 +1,38 @@ +import { ValidationsConfiguration, ValidationWithMessage, Validations } from "../types"; +import { max, maxLength, min, minLength, pattern, required } from "../utils"; + +export default (validations: ValidationsConfiguration = {}): Validations => { + const transformed: Validations = {}; + if (!!validations.required) { + transformed.required = typeof validations.required === 'string' + ? required(validations.required) + : required(); + } + if (validations.min) { + transformed.min = typeof validations.min === 'number' + ? min(validations.min) + : min(validations.min.value as number, validations.min.message); + } + if (validations.max) { + transformed.max = typeof validations.max === 'number' + ? max(validations.max) + : max(validations.max.value as number, validations.max.message); + } + if (validations.minLength) { + transformed.minLength = typeof validations.minLength === 'number' + ? minLength(validations.minLength) + : minLength(validations.minLength.value as number, validations.minLength.message); + } + if (validations.maxLength) { + transformed.maxLength = typeof validations.maxLength === 'number' + ? maxLength(validations.maxLength) + : maxLength(validations.maxLength.value as number, validations.maxLength.message); + } + if (validations.pattern) { + transformed.pattern = !(validations.pattern as ValidationWithMessage)?.value + ? pattern(validations.pattern as RegExp) + : pattern((validations.pattern as ValidationWithMessage).value as RegExp, (validations.pattern as ValidationWithMessage).message as string); + } + return transformed; +} + diff --git a/src/logic/validateField.ts b/src/logic/validateField.ts new file mode 100644 index 0000000..881a13b --- /dev/null +++ b/src/logic/validateField.ts @@ -0,0 +1,20 @@ +import { ValidateFieldParams } from './../types/logic'; + +export default async ({ name, values, formState, _refs }: ValidateFieldParams): Promise => { + if (!Object.keys(_refs[name]._validations).length) { + return + } + if (_refs[name]._disabled) { + return + } + for (const [validationName, validation] of Object.entries(_refs[name]._validations)) { + const result = await validation(values[name]) + formState.errors[name] = { + ...(result !== true && { [validationName]: result }) + } + if (result !== true) { + break; + } + delete formState.errors[name] + } +} \ No newline at end of file diff --git a/src/logic/validateForm.ts b/src/logic/validateForm.ts new file mode 100644 index 0000000..1dea11d --- /dev/null +++ b/src/logic/validateForm.ts @@ -0,0 +1,8 @@ +import { ValidateFormParams } from './../types/logic'; +import validateField from "./validateField" + +export default async (params: ValidateFormParams) => { + for (const name of Object.keys(params.values)) { + await validateField({ ...params, name }) + } +} \ No newline at end of file diff --git a/src/playground/App.vue b/src/playground/App.vue index 18d2afa..b3d4e24 100644 --- a/src/playground/App.vue +++ b/src/playground/App.vue @@ -1,61 +1,36 @@