Skip to content

Commit

Permalink
Merge pull request #134 from CrowdStrike/reset
Browse files Browse the repository at this point in the history
Add support for `reset` button
  • Loading branch information
simonihmig authored May 15, 2023
2 parents d821529 + aeaeca5 commit b3af3d9
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .changeset/fair-games-tan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'ember-headless-form': patch
---

Add support for reset button

Click a native `reset` button will reset the state of the form.
13 changes: 13 additions & 0 deletions packages/ember-headless-form/src/components/headless-form.gts
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,18 @@ export default class HeadlessFormComponent<
}
}

@action
async onReset(e: Event): Promise<void> {
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<FormData<DATA>>,
Expand Down Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions test-app/app/templates/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,9 @@
class='bg-slate-600 text-white rounded px-8 py-1'
data-test-submit
>Submit</button>
<button
type='reset'
class='bg-slate-400 text-white rounded px-8 py-1'
data-test-reset
>Reset</button>
</HeadlessForm>
156 changes: 156 additions & 0 deletions test-app/tests/integration/components/headless-form-reset-test.gts
Original file line number Diff line number Diff line change
@@ -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(<template>
<HeadlessForm @data={{data}} as |form|>
<form.Field @name="firstName" as |field|>
<field.Label>First Name</field.Label>
<field.Input data-test-first-name />
</form.Field>
<form.Field @name="lastName" as |field|>
<field.Label>Last Name</field.Label>
<field.Input data-test-last-name />
</form.Field>
<button type="reset" data-test-reset>Reset</button>
</HeadlessForm>
</template>);

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(<template>
<HeadlessForm @data={{data}} as |form|>
<form.Field @name="firstName" as |field|>
<field.Label>First Name</field.Label>
<field.Input required data-test-first-name />
<field.Errors data-test-first-name-errors />
{{#if field.isInvalid}}
<div data-test-invalid />
{{/if}}
</form.Field>
<form.Field @name="lastName" as |field|>
<field.Label>Last Name</field.Label>
<field.Input data-test-last-name />
<field.Errors data-test-last-name-errors />
</form.Field>
<button type="submit" data-test-submit>Submit</button>
<button type="reset" data-test-reset>Reset</button>
</HeadlessForm>
</template>);

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(<template>
<HeadlessForm @data={{data}} as |form|>
<form.Field @name="firstName" as |field|>
<field.Label>First Name</field.Label>
<field.Input required data-test-first-name />
</form.Field>
<button type="submit" data-test-submit>Submit</button>
<button type="reset" data-test-reset>Reset</button>
{{#if form.validationState}}
<div data-test-validation-state>{{form.validationState.state}}</div>
{{/if}}
</HeadlessForm>
</template>);

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(<template>
<HeadlessForm @data={{data}} @onSubmit={{submitHandler}} as |form|>
<form.Field @name="firstName" as |field|>
<field.Label>First Name</field.Label>
<field.Input data-test-first-name />
</form.Field>
<button type="submit" data-test-submit>Submit</button>
<button type="reset" data-test-reset>Reset</button>
{{#if form.submissionState}}
<div data-test-submission-state>{{form.submissionState.state}}</div>
{{/if}}
</HeadlessForm>
</template>);

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');
});
});
});

0 comments on commit b3af3d9

Please sign in to comment.