Skip to content

Commit

Permalink
feat(FormField): add error-pattern prop (#2601)
Browse files Browse the repository at this point in the history
  • Loading branch information
romhml authored Nov 11, 2024
1 parent 18931ac commit 143612e
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 2 deletions.
2 changes: 1 addition & 1 deletion docs/content/3.components/form.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<FormField name="email">`{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 `<FormField name="email">`{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 `<FormField name="user.email">`{lang="vue"}.

Expand Down
5 changes: 4 additions & 1 deletion src/runtime/components/FormField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ const formField = tv({ extend: tv(theme), ...(appConfig.ui?.formField || {}) })
type FormFieldVariants = VariantProps<typeof formField>
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
Expand Down Expand Up @@ -54,7 +57,7 @@ const ui = computed(() => formField({
const formErrors = inject<Ref<FormError[]> | 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())
Expand Down
30 changes: 30 additions & 0 deletions test/components/Form.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: `
<UForm ref="form" :state="state" :validate="validate">
<UFormField id="emailField" :error-pattern="/(email)\\..*/">
<UInput id="emailInput" v-model="state.email" />
</UFormField>
</UForm>
`
})

const form = wrapper.setupState.form
form.value.submit()
await flushPromises()
expect(wrapper.html()).toContain('Error message')
})
})

0 comments on commit 143612e

Please sign in to comment.