From 143612ec737d1c7571398601c3222f2eed37996e Mon Sep 17 00:00:00 2001 From: Romain Hamel Date: Mon, 11 Nov 2024 18:35:27 +0100 Subject: [PATCH] feat(FormField): add `error-pattern` prop (#2601) --- docs/content/3.components/form.md | 2 +- src/runtime/components/FormField.vue | 5 ++++- test/components/Form.spec.ts | 30 ++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/docs/content/3.components/form.md b/docs/content/3.components/form.md index bf75bab8..23582a76 100644 --- a/docs/content/3.components/form.md +++ b/docs/content/3.components/form.md @@ -64,7 +64,7 @@ It requires two props: :: :: -Errors are reported directly to the [FormField](/components/form-field) component based on the `name` prop. This means the validation rules defined for the `email` attribute in your schema will be applied to ``{lang="vue"}. +Errors are reported directly to the [FormField](/components/form-field) component based on the `name` or `error-pattern` prop. This means the validation rules defined for the `email` attribute in your schema will be applied to ``{lang="vue"}. Nested validation rules are handled using dot notation. For example, a rule like `{ user: z.object({ email: z.string() }) }`{lang="ts"} will be applied to ``{lang="vue"}. diff --git a/src/runtime/components/FormField.vue b/src/runtime/components/FormField.vue index 7c089b6d..4e975d21 100644 --- a/src/runtime/components/FormField.vue +++ b/src/runtime/components/FormField.vue @@ -12,7 +12,10 @@ const formField = tv({ extend: tv(theme), ...(appConfig.ui?.formField || {}) }) type FormFieldVariants = VariantProps export interface FormFieldProps { + /** The name of the FormField. Also used to match form errors. */ name?: string + /** A regular expression to match form error names. */ + errorPattern?: RegExp label?: string description?: string help?: string @@ -54,7 +57,7 @@ const ui = computed(() => formField({ const formErrors = inject | null>('form-errors', null) -const error = computed(() => props.error || formErrors?.value?.find(error => error.name === props.name)?.message) +const error = computed(() => props.error || formErrors?.value?.find(error => error.name === props.name || (props.errorPattern && error.name.match(props.errorPattern)))?.message) const id = ref(useId()) diff --git a/test/components/Form.spec.ts b/test/components/Form.spec.ts index 79b398ec..5ac2e311 100644 --- a/test/components/Form.spec.ts +++ b/test/components/Form.spec.ts @@ -363,4 +363,34 @@ describe('Form', () => { expect(wrapper.setupState.onError).toHaveBeenCalledTimes(0) }) }) + + test('form field errorPattern works', async () => { + const wrapper = await mountSuspended({ + components: { + UFormField, + UForm, + UInput + }, + setup() { + const form = ref() + const state = reactive({}) + function validate() { + return [{ name: 'email.1', message: 'Error message' }] + } + return { state, validate, form } + }, + template: ` + + + + + + ` + }) + + const form = wrapper.setupState.form + form.value.submit() + await flushPromises() + expect(wrapper.html()).toContain('Error message') + }) })