-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add documentation on updating and resetting form state #144
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'docs-app': patch | ||
--- | ||
|
||
Add documentation on updating and resetting form state |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
--- | ||
title: Async state | ||
order: 6 | ||
order: 7 | ||
--- | ||
|
||
# Managing asynchronous state | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
# Resetting dirty form state | ||
|
||
The following kitchen-sink like example shows all three ways to reset form state: | ||
|
||
- by clicking the native reset button | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: I think this can be split into multiple demos. My concern is that folks with copy-paste this and have all three methods (when perhaps they just need the native reset button). Could be
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I currently don't have much time, so I decided to merge this as-is, but created this issue to pick up and track your suggestion: #149 |
||
- by clicking the link, using the yielded `reset` action | ||
- by calling `reset` using the register pattern described above when selecting a different user | ||
|
||
```hbs template | ||
<div class='flex gap-8'> | ||
<div class='flex-initial'> | ||
Select user: | ||
<ul> | ||
{{#each this.users as |user index|}} | ||
<li><a | ||
class='cursor-pointer' | ||
{{on 'click' (fn this.selectUser index)}} | ||
>{{user.firstName}} | ||
{{user.lastName}}</a></li> | ||
{{/each}} | ||
</ul> | ||
</div> | ||
|
||
<HeadlessForm | ||
@data={{this.currentUser}} | ||
@onSubmit={{this.handleSubmit}} | ||
class='flex-1' | ||
as |form| | ||
> | ||
{{(this.assignReset form.reset)}} | ||
|
||
<form.Field @name='firstName' as |field|> | ||
<div class='my-2 flex flex-col'> | ||
<field.Label>First name</field.Label> | ||
<field.Input required class='border rounded px-2' /> | ||
<field.Errors /> | ||
</div> | ||
</form.Field> | ||
|
||
<form.Field @name='lastName' as |field|> | ||
<div class='my-2 flex flex-col'> | ||
<field.Label>Last name</field.Label> | ||
<field.Input required class='border rounded px-2' /> | ||
<field.Errors /> | ||
</div> | ||
</form.Field> | ||
|
||
<button type='submit'>Submit</button> | ||
<button type='reset'>Reset</button> | ||
|
||
<p>Click on the reset button above or | ||
<a {{on 'click' form.reset}}>here</a> | ||
to reset any dirty state</p> | ||
</HeadlessForm> | ||
</div> | ||
``` | ||
|
||
```js component | ||
import Component from '@glimmer/component'; | ||
import { tracked } from '@glimmer/tracking'; | ||
import { action } from '@ember/object'; | ||
|
||
export default class MyFormComponent extends Component { | ||
users = [ | ||
{ | ||
firstName: 'Jane', | ||
lastName: 'Doe', | ||
}, | ||
{ | ||
firstName: 'John', | ||
lastName: 'Smith', | ||
}, | ||
]; | ||
|
||
@tracked | ||
selectedIndex = 0; | ||
|
||
resetForm; | ||
|
||
@action | ||
assignReset(reset) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: maybe there should be a comment here that this is only necessary if you want to do something with the |
||
this.resetForm = reset; | ||
} | ||
|
||
get currentUser() { | ||
return this.users[this.selectedIndex]; | ||
} | ||
|
||
@action | ||
selectUser(index) { | ||
this.selectedIndex = index; | ||
this.resetForm?.(); | ||
} | ||
|
||
handleSubmit({ firstName, lastName }) { | ||
alert(`Form submitted with: ${firstName} ${lastName}`); | ||
} | ||
} | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
--- | ||
title: Resetting state | ||
order: 6 | ||
--- | ||
|
||
# Resetting form state | ||
|
||
As explained in the chapter for [Updating data](./data#updating-data), form state consists of the original immutable data passed to `@data` and "dirty" changed state. To keep the form component in place but get rid of the dirty state, you need to explicitly call a `reset` action on the form. There are different ways to do that: | ||
|
||
- use "the platform" and make the user click on a `<button type="reset">` | ||
- use the yielded `reset` action | ||
|
||
For the latter case, this is easy to do when the place where you want to call `reset` is within the block of `<HeadlessForm as |form|>`. For example you can pass it to the `on` modifier, is in `{{on "click form.reset}}`. | ||
|
||
However there is another interesting use case where you might want to reset form state from "outside" the component, for example in a controller action. The problem here is that you do not have access to the yielded `reset` action there. | ||
But you can follow the following pattern to solve that: | ||
|
||
- create a function/method that receives the `reset` action (it's just a function) and assign it to the context where you will later be able to access it, like the controller for example | ||
- invoke that function as a helper (in modern Ember, helpers are really just functions) within the form template block where you have access to the scope of the yielded `form` API | ||
- call this registered reset function whenever you need to | ||
|
||
Note that besides resetting dirty data, the form will also reset any [validation](../validation) state and errors it might had before! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Total nit: I like the link to resetting here, but I would like a code snippet on either this page or the
reset
page on how to reset.Reason being, I think folks scan until they see a code sample and likely copy-paste it.