Search code examples
formsangular

How can I detect/watch "dirty-status" of an angular2-form in the right way?


I have a form in Angular2 (e.g)

<form id="myLovelyForm" name="myLovelyForm" #myLovelyForm="ngForm">
    <label [attr.for]="myLovelyCheckbox">
      <input [attr.id]="myLovelyCheckbox" type="checkbox"
             [(ngModel)]="myLovelyCheckbox">
      <span class="myLovelyCheckbox">myLovelyCheckbox</span>
    </label>
</form>

and an animation, which should start, if the form is dirty:

<div 
    id="myLovelyNotification" 
    class="myLovelyNotification" 
    [@notification]="myLovelyForm.form.dirty">
.....
.....
</div>

The animation works properly if I set [@notification] = true, but my myLovelyForm.dirty does not fire, if I touch the form and change an element.

If the @notification is false, the animation stops, i.e. if the checkbox was selected before and I unselect it mistakenly and select it again, the form is not pristine (touched) but not dirty anymore, therefore the animation should stop. If I set the @notification = false manually, it works properly.

The big question is: How can I detect/watch "dirty-status" of an angular2-form in the right way?


Solution

  • You can subscribe to form changes:

    this.physicalForm.valueChanges
       .map((value) => {
          return value;
       })
       .subscribe((value) => {
          if(this.selectedPhysical.weight != this.physicalForm.value.weight)  {      
            this.selectedPhysical.weight = this.physicalForm.value.weight;
          }
          this.isDirty == this.physicalForm.touched;
       });
    

    If this event fires, then you know your form is dirty.

    this is an example from my actual app (nut.abbr is the formcontrolName):

    ngOnInit() {
       for (let nut of this.userSettings.nutrientData) {
          this.foodSettingsForm.controls[nut.abbr].valueChanges
             .subscribe(v => { console.log("value: ", v); this.completeValueChange(nut.abbr, v); });
       }
    }
    
    completeValueChange(field: string, value: boolean) {
       this.isChanged = true;
       Nutrient.updateNutrient(field, value, this.userSettings.nutrientData);
    }