Skip to content

Commit

Permalink
feat: sync errors to native input validity
Browse files Browse the repository at this point in the history
  • Loading branch information
logaretm committed Aug 3, 2024
1 parent 3077741 commit e1a7190
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 4 deletions.
28 changes: 26 additions & 2 deletions packages/core/src/validation/useInputValidity.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ref } from 'vue';
import { nextTick, ref } from 'vue';
import { useInputValidity } from './useInputValidity';
import { fireEvent, render, screen } from '@testing-library/vue';
import { useFormField } from '../form';
import { FormField, useFormField } from '../form';

test('updates the validity state on blur events', async () => {
const input = ref<HTMLInputElement>();
Expand Down Expand Up @@ -72,3 +72,27 @@ test('updates the validity on specified events', async () => {
await fireEvent.input(screen.getByTestId('input'), { target: { value: 'test' } });
expect(screen.getByTestId('err').textContent).toBe('');
});

test('updates the input native validity with custom validity errors', async () => {
const input = ref<HTMLInputElement>();
let field!: FormField<any>;
await render({
setup: () => {
field = useFormField();
useInputValidity({ inputRef: input, field, events: ['input'] });

return { input, errorMessage: field.errorMessage };
},
template: `
<form>
<input ref="input" data-testid="input" />
<span data-testid="err">{{ errorMessage }}</span>
</form>
`,
});

field.setErrors('Custom error');
await nextTick();
expect(screen.getByTestId('err').textContent).toBe('Custom error');
expect(input.value?.validationMessage).toBe('Custom error');
});
13 changes: 11 additions & 2 deletions packages/core/src/validation/useInputValidity.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Ref, inject, nextTick, onMounted, shallowRef } from 'vue';
import { Ref, inject, nextTick, onMounted, shallowRef, watch } from 'vue';
import { useEventListener } from '../helpers/useEventListener';
import { FormField, FormKey } from '../form';

Expand All @@ -9,7 +9,7 @@ interface InputValidityOptions {
}

export function useInputValidity(opts: InputValidityOptions) {
const { setErrors } = opts.field;
const { setErrors, errorMessage } = opts.field;
const validityDetails = shallowRef<ValidityState>();
const form = inject(FormKey, null);

Expand All @@ -28,6 +28,15 @@ export function useInputValidity(opts: InputValidityOptions) {

form?.onSubmitted(updateValiditySync);

if (opts.inputRef) {
watch(errorMessage, msg => {
const inputMsg = opts.inputRef?.value?.validationMessage;
if (inputMsg !== msg) {
opts.inputRef?.value?.setCustomValidity(msg || '');
}
});
}

/**
* Validity is always updated on mount.
*/
Expand Down

0 comments on commit e1a7190

Please sign in to comment.