diff --git a/packages/vee-validate/src/Field.ts b/packages/vee-validate/src/Field.ts index d07f9c04d..89a0782ed 100644 --- a/packages/vee-validate/src/Field.ts +++ b/packages/vee-validate/src/Field.ts @@ -191,6 +191,14 @@ export const Field = defineComponent({ }; } + ctx.expose({ + setErrors, + setTouched, + reset: resetField, + validate: validateField, + handleChange, + }); + return () => { const tag = resolveDynamicComponent(resolveTag(props, ctx)) as string; const children = normalizeChildren(tag, ctx, slotProps); diff --git a/packages/vee-validate/tests/Field.spec.ts b/packages/vee-validate/tests/Field.spec.ts index 792835dca..1f7929d66 100644 --- a/packages/vee-validate/tests/Field.spec.ts +++ b/packages/vee-validate/tests/Field.spec.ts @@ -1003,4 +1003,34 @@ describe('', () => { await flushPromises(); expect((form as any).field).toBe('hello'); }); + + test('resets validation state using refs and exposed API', async () => { + const wrapper = mountWithHoc({ + template: ` +
+ + + {{ errors && errors[0] }} + + + +
+ `, + }); + + const error = wrapper.$el.querySelector('#error'); + const input = wrapper.$el.querySelector('input'); + + expect(error.textContent).toBe(''); + + setValue(input, ''); + await flushPromises(); + expect(error.textContent).toBe(REQUIRED_MESSAGE); + setValue(input, '123'); + await flushPromises(); + wrapper.$el.querySelector('button').click(); + await flushPromises(); + expect(error.textContent).toBe(''); + expect(input.value).toBe(''); + }); });