diff --git a/playground/app/components/FormElementsExample.vue b/playground/app/components/FormElementsExample.vue index a9ce8a14..75e3676d 100644 --- a/playground/app/components/FormElementsExample.vue +++ b/playground/app/components/FormElementsExample.vue @@ -32,7 +32,7 @@ const schema = z.object({ slider: z.number().max(20, { message: 'Must be less than 20' }) }) -type Schema = z.output +type Schema = z.input const state = reactive>({}) diff --git a/src/runtime/components/Form.vue b/src/runtime/components/Form.vue index c1890f0f..2ce0c090 100644 --- a/src/runtime/components/Form.vue +++ b/src/runtime/components/Form.vue @@ -94,13 +94,13 @@ onUnmounted(() => { const errors = ref([]) provide('form-errors', errors) -const inputs = ref>({}) +const inputs = ref>({}) provide(formInputsInjectionKey, inputs) function resolveErrorIds(errs: FormError[]): FormErrorWithId[] { return errs.map(err => ({ ...err, - id: inputs.value[err.name] + id: inputs.value[err.name]?.id })) } @@ -129,7 +129,7 @@ async function getErrors(): Promise { } async function _validate(opts: { name?: string | string[], silent?: boolean, nested?: boolean } = { silent: false, nested: true }): Promise { - const names = opts.name && !Array.isArray(opts.name) ? [opts.name] : opts.name + const names = opts.name && !Array.isArray(opts.name) ? [opts.name] : opts.name as string[] const nestedValidatePromises = !names && opts.nested ? Array.from(nestedForms.value.values()).map( @@ -143,9 +143,16 @@ async function _validate(opts: { name?: string | string[], silent?: boolean, nes : [] if (names) { - const otherErrors = errors.value.filter(error => !names!.includes(error.name)) - const pathErrors = (await getErrors()).filter(error => names!.includes(error.name) - ) + const otherErrors = errors.value.filter(error => !names.some((name) => { + const pattern = inputs.value?.[name]?.pattern + return name === error.name || (pattern && error.name.match(pattern)) + })) + + const pathErrors = (await getErrors()).filter(error => names.some((name) => { + const pattern = inputs.value?.[name]?.pattern + return name === error.name || (pattern && error.name.match(pattern)) + })) + errors.value = otherErrors.concat(pathErrors) } else { errors.value = await getErrors() diff --git a/src/runtime/components/FormField.vue b/src/runtime/components/FormField.vue index 4e975d21..deb8aec8 100644 --- a/src/runtime/components/FormField.vue +++ b/src/runtime/components/FormField.vue @@ -68,7 +68,8 @@ provide(formFieldInjectionKey, computed(() => ({ name: props.name, size: props.size, eagerValidation: props.eagerValidation, - validateOnInputDelay: props.validateOnInputDelay + validateOnInputDelay: props.validateOnInputDelay, + errorPattern: props.errorPattern }) as FormFieldInjectedOptions)) diff --git a/src/runtime/composables/useFormField.ts b/src/runtime/composables/useFormField.ts index 88085714..249aa8c2 100644 --- a/src/runtime/composables/useFormField.ts +++ b/src/runtime/composables/useFormField.ts @@ -19,7 +19,7 @@ export const formOptionsInjectionKey: InjectionKey> = Symbol('nuxt-ui.form-events') export const formFieldInjectionKey: InjectionKey>> = Symbol('nuxt-ui.form-field') export const inputIdInjectionKey: InjectionKey> = Symbol('nuxt-ui.input-id') -export const formInputsInjectionKey: InjectionKey>> = Symbol('nuxt-ui.form-inputs') +export const formInputsInjectionKey: InjectionKey>> = Symbol('nuxt-ui.form-inputs') export const formLoadingInjectionKey: InjectionKey>> = Symbol('nuxt-ui.form-loading') export function useFormField(props?: Props, opts?: { bind?: boolean }) { @@ -38,7 +38,7 @@ export function useFormField(props?: Props, opts?: { bind?: boolean }) { inputId.value = props?.id } if (formInputs && formField.value.name && inputId.value) { - formInputs.value[formField.value.name] = inputId.value + formInputs.value[formField.value.name] = { id: inputId.value, pattern: formField.value.errorPattern } } } diff --git a/src/runtime/types/form.ts b/src/runtime/types/form.ts index d0469a57..d2b92236 100644 --- a/src/runtime/types/form.ts +++ b/src/runtime/types/form.ts @@ -82,6 +82,7 @@ export interface FormFieldInjectedOptions { error?: string | boolean eagerValidation?: boolean validateOnInputDelay?: number + errorPattern?: RegExp } export class FormValidationException extends Error {