-
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
Issues resetting form data #117
Comments
I agree we need to support this, will look into this! |
I noticed that resetting the form (using a simple |
Yup (pun intended): #122 |
I worked on an elaborate solution for this, until I realized it actually does not serve the use case. 🙈😅 So back to the drawing board, trying to properly design this first before implementing it... For some additional context: headless-form takes the approach of being strict about DDAU, even though in the case of forms there are some more or less valid cases for allowing two-way bindings maybe. But we don't do this, so the user will only get the new data by receiving it from Im trying to incorporate the different cases of the state of the input (pristine - has never been touched by the user - vs. dirty - user has entered a different value than the initial one) and the action that is happening (already taking into account #122 here in the last two columns). Here is an initial suggestion for further discussion:
I think we don't want the user provided value to be lost when I am unsure about col 2, row 2: when reassigning If we don't do this (i.e. keep the dirty value), we would still have no way to programmatically reset the form "from the outside". Another pattern that would allow this, which is not listed in the table above, is "Action down": letting the form call some kind of register callback, that gives the parent a reference to a reset-action that they can call (instead of relying on data to just flow down). PowerSelect uses a similar concept. Tbh I am not really a fan of it in general, as it can cause a bunch of problems (does not automatically account for the lifecycle of a component, so you can end up with some kind of "dangling pointer" to a reset action of an already destroyed component (that doesn't get garbage collected while the pointer exists)... Thoughts? /cc @ynotdraw @nicolechung @NullVoxPopuli |
Btw, there was an existing test covering some parts of what is mentioned above, but which was skipped for now, as indeed the logic we want here was not quite clear yet. So I think it's good to have this issue raised here, so we can get back to this! |
This ask above sounds related to this comment below:
Am I reading this correctly? |
Looks like Angular has a So in the case of If Another option seems to be being able to pass the form value to |
Hm, not sure, I'll try to clarify this...
So I would read this as the last option (column) in my table above: "yielded reset action called", as in: <HeadlessForm @data={{this.data}} as |form|>
{{! form stuff }}
<button type="button" {{on "click" form.reset}}>Reset</button>
</HeadlessForm> Here we are yielding an action <HeadlessForm @data={{this.data}} as |form|>
{{! form stuff }}
<button type="reset">Reset</button>
</HeadlessForm> This is easy to do, as yielding down something will make it available to the block, and if that's where we want to use it, then that's fine. A different case is yielding up. Like you want to call
An example of this would be: // template.hbs
<HeadlessForm @data={{this.data}} @registerForm={{this.registerForm}} as |form|>
...
</HeadlessForm> // controller.js
export default class FormController extends Controller {
data = {};
formApi;
@action
registerForm(formApi) {
this.formApi = formApi;
}
someAction() {
// do something, like saving a record based on the form data, and then resetting the form...
this.formApi.reset();
}
} Here, with Again, I don't really like this very much, and would rather avoid this where possible, but it is an option on the table... Regarding your references to Angular, I don't know enough about Angular to see how that could translate to Ember 😅
Not sure what means exactly. Can you show or link to an example? |
Maybe we can do something a bit like what References
export default class FormController extends Controller {
const { reset } = useForm();
someAction() {
// do something, like saving a record based on the form data, and then resetting the form...
const values = await save('some-api', formValues);
reset(values, { keepDirtyValues: true });
}
} I don't really know enough Angular either, so sticking with the I don't have suggestions for how this would work with the current implementation however - how would the |
Unless we can do something like
Where the |
Yeah, but this works only if the users interaction originated from within the form. Let's give an example where this does not work: say we have a list of records and a sidebar. when you click a record, it will be highlighted in the list, and a form with the records data will show up in the sidebar, to allow editing it. Now if the user has entered some new data there, but didn't submit it, but instead selected a different record, we'll want to show that record's data in the form. But we also don't want the dirtied fields to preserve their value, as those were related to a totally different record. Se we want to discard all temporary changes in the form, and let the form just show the new |
Also, we can look at this problem from two angles. First is how to support the use case of resetting the form. But whatever we come up with, we still have to also answer the question what the form should do in those cases that are contained in that table above: given we have dirtied fields, what should happen with those in case of 1) updating So the question there is basically: what would a user (you!) expect? |
This got me thinking...
Yeah, that is the tricky part, how to make this work with Ember, where we don't have hooks, but we "only" have some data flowing down. We still want to call a Picking up your example, and modifying it a bit to fit how this could work with Ember: import { useForm } from 'ember-headless-form';
export default class FormController extends Controller {
formController = useForm();
data = {};
someAction() {
// do something, like saving a record based on the form data, and then resetting the form...
const values = await save('some-api', formValues);
this.formController.reset();
}
} <HeadlessForm @data={{this.data}} @controller={{this.formController}} as |form|>
...
</HeadlessForm> Ignore the hard part of naming things here (e.g. "controller"), that remains to be seen... but how it basically could work is that It's gotten late over here, and I need to sleep over this, but to me this looks like an pretty interesting approach, that I didn't have on my mind before. Thanks a bunch for bringing this up @nicolechung! |
I'm a bit late, but after catching up - I think what you landed on above @simonihmig (with @nicolechung ) looks great to me. Also exposing it via the yielded form ( |
A couple of thoughts... ember-basic-dropdown does a nice job of yielding actions that impact the component as a a hash of actions like:
and you can pass those actions as arguments to other functions like:
I like the
|
I would say though that in my view, here's what i would expect to happen.
If that reset button is clicked, the data that's passed into the form has now changed and the form should respect the data that was passed down into it. Thats (to me) how "Data Down" would ideally be reflected here. The form takes whatever data it's given and presents it, then calls an action to do something to act on it. When that wasn't how it worked, I was pretty surprised and assumed it was a bug. I think it's totally fine if the new object clobbers the old -- the form wasn't submitted, so the changes are thrown away. |
@averydev so what you are saying is that you would expect this to be our behavior, right? (pay attention to cols 1+2, row 2)
Means, whenever something changes around |
Nice ideas above. WDYT about the idea of passing the <HeadlessForm @data={{this.formData}} @onSubmit={{this.handleSubmit}}>
</HeadlessForm> @action
handleSubmit(data, resetForm) {
// save the data
resetForm();
} |
@herzzanu yeah, this would work, but only if resetting happens when (after) submitting. In this comment I gave an example of a use case that would also require resetting unrelated to submission. And ideally we would have a single API that covers both cases. |
Right, I missed that. In that case, I guess this example you mentioned, makes even more sense. |
On the other side, do you see a downside of a mixed solution between what I suggested above and your example? We know most of the time reset would happen after the form is submitted, so maybe we should offer an easy, straight forward way to call |
There is this option? Always available to the style of api headless form provides (and maintainers don't need to change what is supported): <HeadlessForm @data={{this.data}} as |form|>
{{ ( this.assignFormApis form )}}
</HeadlessForm assignFormApis(form) {
this.resetForm = form.reset
} |
The discussion here fluctuated a bit between supporting the specific use case of resetting (e.g. by calling some kind of |
Part of #117, this adds support for resetting the state of the form using a native reset button. Yielding a `reset` action will come in a separate PR.
Part of #117, this adds support for resetting the state of the form using a native reset button. Yielding a `reset` action will come in a separate PR.
@simonihmig I assume we can resolve this one based on the latest changes. |
Yeah, I think so. I wanted to provide some examples of resetting forms in the docs, and demonstrate the different use cases. But no need to wait if you want to try that. 1.0.0-beta.3 has been released yesterday! |
Hi there!
I'm having an issue resetting / changing the form data values.
My use case is a form and a list, where after you add an item via a HeadlessForm, it is added to the list, the values are cleared, and you can create a new item.
@data
doesn't reset the values present in the form@data
to a new object also doesn't effect values in the formIdeally either there would be a yielded method to change the data, or mutating the data via another approach would effect the data in the form.
The text was updated successfully, but these errors were encountered: