diff --git a/packages/ember-headless-form/src/components/headless-form.gts b/packages/ember-headless-form/src/components/headless-form.gts index 83121363..43bc5169 100644 --- a/packages/ember-headless-form/src/components/headless-form.gts +++ b/packages/ember-headless-form/src/components/headless-form.gts @@ -462,6 +462,18 @@ export default class HeadlessFormComponent< } } + @action + async onReset(e: Event): Promise { + e.preventDefault(); + + for (const key of Object.keys(this.internalData)) { + delete this.internalData[key as keyof DATA]; + } + + this.validationState = undefined; + this.submissionState = undefined; + } + @action registerField( name: FormKey>, @@ -562,6 +574,7 @@ export default class HeadlessFormComponent< ...attributes {{this.registerForm}} {{on "submit" this.onSubmit}} + {{on "reset" this.onReset}} {{this.onValidation this.fieldValidationEvent this.handleFieldValidation}} {{this.onValidation this.fieldRevalidationEvent diff --git a/test-app/app/templates/index.hbs b/test-app/app/templates/index.hbs index e04d6fc6..8d6912d3 100644 --- a/test-app/app/templates/index.hbs +++ b/test-app/app/templates/index.hbs @@ -103,4 +103,9 @@ class='bg-slate-600 text-white rounded px-8 py-1' data-test-submit >Submit + \ No newline at end of file diff --git a/test-app/tests/integration/components/headless-form-reset-test.gts b/test-app/tests/integration/components/headless-form-reset-test.gts new file mode 100644 index 00000000..fb9776ce --- /dev/null +++ b/test-app/tests/integration/components/headless-form-reset-test.gts @@ -0,0 +1,156 @@ +/* eslint-disable no-undef -- Until https://github.com/ember-cli/eslint-plugin-ember/issues/1747 is resolved... */ +/* eslint-disable simple-import-sort/imports,padding-line-between-statements,decorator-position/decorator-position -- Can't fix these manually, without --fix working in .gts */ + +import { click, fillIn, render } from '@ember/test-helpers'; +import { module, test } from 'qunit'; + +import { HeadlessForm } from 'ember-headless-form'; +import { setupRenderingTest } from 'test-app/tests/helpers'; + +interface TestFormData { + firstName?: string; + lastName?: string; +} + +module('Integration Component HeadlessForm > Reset', function (hooks) { + setupRenderingTest(hooks); + + module('reset button', function () { + test('dirty fields are resetted', async function (assert) { + const data: TestFormData = { firstName: 'Tony', lastName: 'Ward' }; + + await render(); + + await fillIn('[data-test-first-name]', 'Nicole'); + await click('[data-test-reset'); + + assert.dom('[data-test-first-name]').hasValue('Tony'); + assert.dom('[data-test-last-name]').hasValue('Ward'); + }); + + test('validation errors are cleared', async function (assert) { + const data: TestFormData = {}; + + await render(); + + await click('[data-test-submit]'); + + assert + .dom('[data-test-first-name-errors]') + .exists({ count: 1 }, 'validation errors appear when validation fails'); + assert.dom('[data-test-first-name]').hasAria('invalid', 'true'); + assert.dom('[data-test-invalid]').exists(); + + await click('[data-test-reset]'); + + assert + .dom('[data-test-first-name-errors]') + .doesNotExist('validation errors are removed on reset'); + assert.dom('[data-test-first-name]').doesNotHaveAria('invalid'); + assert.dom('[data-test-invalid]').doesNotExist(); + }); + + test('validation state is resetted', async function (assert) { + const data: TestFormData = {}; + + await render(); + + assert + .dom('[data-test-validation-state]') + .doesNotExist( + 'form.validationState is not present until first validation' + ); + + await click('[data-test-submit]'); + + assert + .dom('[data-test-validation-state]') + .hasText('RESOLVED', 'form.validationState has resolved'); + + await click('[data-test-reset]'); + + assert + .dom('[data-test-validation-state]') + .doesNotExist('form.validationState is resetted'); + }); + + test('submission state is resetted', async function (assert) { + const data: TestFormData = {}; + const submitHandler = () => 'ok'; + + await render(); + + assert + .dom('[data-test-submission-state]') + .doesNotExist( + 'form.submissionState is not present until first validation' + ); + + await click('[data-test-submit]'); + + assert + .dom('[data-test-submission-state]') + .hasText('RESOLVED', 'form.submissionState has resolved'); + + await click('[data-test-reset]'); + + assert + .dom('[data-test-submission-state]') + .doesNotExist('form.submissionState is resetted'); + }); + }); +});