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

feat(forms): add ability to reset forms #9974

Merged
merged 1 commit into from Jul 12, 2016

Conversation

Projects
None yet
9 participants
@kara
Contributor

kara commented Jul 11, 2016

This PR adds the ability to reset forms programmatically. Calling reset() at any level will:

  • Mark the control and any child controls as pristine
  • Mark the control and any child controls as untouched
  • Set the value of control and child controls to custom value (if provided) or null
  • Update value/validity/errors of affected parties

Usage

@Component({
   selector: 'my-comp',
   template: '
      <div [formGroup]="form">
         <input formControlName="first">
         <input formControlName="last">
      </div>
   '
})
class MyComp {
   form = new FormGroup({
      first: new FormControl('Nancy'),
      last: new FormControl('Drew')
   });
}

   reset() {
      this.form.reset();  // will reset to null
     // this.form.reset({first: 'Nancy', last: 'Drew'});   -- will reset to value specified
   }

You can also call markAsPristine() or markAsUntouched() individually at any level if you'd like more fine-tuned control.

This PR also ensures that native reset buttons reset the form automatically. In other words, clicking the following button will reset all your form fields to null in both the UI and in your model:

<button type="reset">RESET</button>
@kara

This comment has been minimized.

Contributor

kara commented Jul 12, 2016

@vkniazeu, this PR isn't the right place to report an issue with the docs examples. Please file an issue here: https://github.com/angular/angular.io.

@@ -48,4 +48,8 @@ export abstract class AbstractControlDirective {
}
get path(): string[] { return null; }
reset(value?: any): void {

This comment has been minimized.

@vsavkin

vsavkin Jul 12, 2016

Contributor

Even though it doesn't matter, I think the intent is clearer when you use reset(value: any = undefined). The reason is you always use the value, the value is not optional. It is just you use 'default' when the value is not provided.

Also, I thought you were going to default to null, not to undefined.

@@ -329,19 +389,28 @@ export class FormControl extends AbstractControl {
* via an `onChange` event. This is the default behavior if `emitModelToViewChange` is not
* specified.
*/
updateValue(value: any, {onlySelf, emitEvent, emitModelToViewChange}: {
updateValue(value: any, {onlySelf, emitEvent, emitModelToViewChange, emitViewToModelChange}: {

This comment has been minimized.

@vsavkin

vsavkin Jul 12, 2016

Contributor

update API docs to describe what emitViewToModelChange does?

This comment has been minimized.

@kara

kara Jul 12, 2016

Contributor

Good catch. Doing so now.

@kara kara merged commit da8eb9f into angular:master Jul 12, 2016

3 checks passed

ci/circleci Your tests passed on CircleCI!
Details
cla/google All necessary CLAs are signed
continuous-integration/travis-ci/pr The Travis CI build passed
Details
@iorlas

This comment has been minimized.

iorlas commented Jul 13, 2016

Hoooraaay! 🍻

@robinkedia

This comment has been minimized.

robinkedia commented Aug 8, 2016

Hi - Can we have the documentation updated on how to reset using new forms? Do we have to use formgroup to reset pristine state?

@kara kara added the comp: forms label Sep 5, 2016

@DeusProx

This comment has been minimized.

DeusProx commented Sep 6, 2016

Hey, I don't know if I should open a new issue with a feature request for the following but I think it would be good to first talk about my idea here:

  1. We set default values when creating the FormGroup so in my opinion the "pristine" state would be the state when each of our default values is set. So reset() should set the defaults values otherwise it would be just easier to just don't specify default values at all and afterwards set them with reset({first: 'Nancy', last: 'Drew'})
  2. I also think that it is a bit confusing to use reset({first: 'Nancy', last: 'Drew'}); to set values... As I said "I set values" so it's a setter function not a reset function.

So in my opnion the following changes would be the best:

form = new FormGroup({
   first: new FormControl('Nancy'),
   last: new FormControl('Drew')
});
...
this.form.reset(); // resets to default values e.g. {first: 'Nancy', last: 'Drew'}
this.form.resetToNull(); // resets to null e.g. {first: '', last: ''}
this.form.resetAndSetValue({first: 'James'}); // resets to the specified value e.g. {first:'James', last:''}

We can argue about naming or even different changes but atm it's just counterintuitive.

@kara

This comment has been minimized.

Contributor

kara commented Sep 7, 2016

@DeusProx To give you some background, the reset() function is intended to mimic the functionality of a native reset button. In HTML5 forms, when you reset a form, it simply empties all the values and it doesn't reset to any default value. This is how our default behavior works as well.

When you call reset() with an argument, you're actually resetting to a certain state, not just to a value. Every property of a form control can be calculated except two parts: the value and whether or not the control is disabled. Consequently, you can pass both these properties in when setting an initial state (when you instantiate a FormControl instance) or resetting to a certain state (with reset()).

So you can also do this:

this.form.reset({
   first: {value: 'Carson', disabled: true}
   last: {value: 'Drew', disabled: false}
})

Also keep in mind that what you're suggesting would be a significant breaking change for users. I'd like to avoid breaking applications unless there's a compelling reason, and in this case, I think the existing behavior that mimics native forms makes more sense.

That said, I can see where you're coming from and we always appreciate the feedback.

@DeusProx

This comment has been minimized.

DeusProx commented Sep 7, 2016

@kara I understand your reasoning. Especially that you want to mimic a native reset button and use a common naming scheme. I surely can agree on that after your post! Still one should think about a functionality to fill in the default values automatically which we defined in the formgroup/formbuilder otherwise I don't even see a reason why we should specify them from the start.

We could alternatively just specify the form and it's validators in the first step and then write a function which uses this.form.reset({...}) on ngOnInit to fill in the data and reuse this function everytime we need to reset the data... I mean most of the times we want to provide the same initial value for every run through the form, won't we?
It's just some weird kind of boilerplate if we need to code the same behaviour two times in different ways to achieve the same result.

@zoechi

This comment has been minimized.

Contributor

zoechi commented Sep 10, 2016

@DeusProx If you move the code that creates the FormGroup to a method, you can just recreate the FormGroup in it's default state (supported added in RC.6 or with the next update)

@DeusProx

This comment has been minimized.

DeusProx commented Sep 11, 2016

@zoechi I know that. i recently read in another issue that this was the "common version" of a reset in earlier versions. I also thought of this but is this really a good solution? I don't know about any side effects or performance problems. Could there be problems?

@zoechi

This comment has been minimized.

Contributor

zoechi commented Sep 12, 2016

@DeusProx

or performance problems.

How many times per second do you plan to reset the form? ;-)
I wouldn't expect side effects or performance problems

@laxmikanta415

This comment has been minimized.

laxmikanta415 commented Oct 24, 2017

Reseting the form in simple javascript is the solution for now.

var form : HTMLFormElement = document.getElementById('id');
form.reset();

@AlwaysAbhl001

This comment has been minimized.

AlwaysAbhl001 commented Jun 11, 2018

How many times per second do you plan to reset the form? ;-)
I wouldn't expect side effects or performance problems

@zoechi right now I'm facing this. We are serving <= per second a new work to user after he/she submit current work. In this situation after loading the new values our form reset 👎 .

submit(){ this.form.reset(); this.field1 = valueField1; }

Any alternative way for this ?

and even we validating only after form.submit but still validations occurred after resetting(it clearing new values but not submitting(IMO)). why it is happening ? previous work submit action still in active ? or form.reset() also calls submit function ?.

@zoechi

This comment has been minimized.

Contributor

zoechi commented Jun 11, 2018

@AlwaysAbhl001 I'd suggest to create a new issue with a StackBlitz/Plunker to reproduce.
This PR is closed and any comments probably just ignored.

@AlwaysAbhl001

This comment has been minimized.

AlwaysAbhl001 commented Jun 12, 2018

@zoechi here it is repro

@zoechi

This comment has been minimized.

Contributor

zoechi commented Jun 12, 2018

@AlwaysAbhl001 ignoring half of my comment won't help you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment