2

I have a reactive form that I want to detect changes for. For example, when a user views a product, a "view product" page opens filling in all form fields with the details of that product. If a change is made to any value in the form, I want a "Save" button to be enabled (it is disabled by default). However, if the user undos the changes or reverts back to what it was on load, the Save button will be disabled again.

Is this possible? I've seen some people do it where angular detects form changes and makes the form "dirty" but once the form has been dirtied it isn't easy or intuitive to change the state back to pristine. I've also read where people load the initial product details into local storage and compare the form values JSON of the current state to the local storage JSON and enable/disable buttons based on that. Does anyone have a preferred or better method?

Thanks

2 Answers 2

4

When the initial data arrives, save it locally as a component property. You can then compare it to the form's current values at any time to figure out whether there has been a change.

You'll need:

  • initValues, the starting form values (before user interaction)

  • disableSaveBtn:boolean property that is bound to the button in the template with: [disabled]="disableSaveBtn"

  • valuesMatch(val1,val2):boolean function that will compare two models of the form and return true if they match

Do the comparison each time the form value change. Since you're using reactive forms, you can just listen to the valueChanges observable

// will emit every time a form control value is changed
this.form.valueChanges.subscribe(newValues => {
    // disable the button if new value matches initial value
    this.disableSaveBtn = this.valuesMatch(newValues, initValues)
})
Sign up to request clarification or add additional context in comments.

3 Comments

i implemented your suggestion, just comparing the JSON and it works very well. It seems so simple in hind sight that I am ashamed I did not think of it :) Thanks! @BeetleJuice
You're welcome. If you liked the answer, please remember to upvote.Did you need a custom function to compare the JSON?
That would be nice (always good to see what others have out there). I do have something in place, in my particular instance I need to compare specific fields within the JSON rather than the entire thing, but I have something working.
2

Building on what BeetleJuice mentioned:

Finding out what is dirty: JSON stringify comparison works for deeply nested objects and seems less expensive than tracking all form controls individually because of all the observables that would be created that the browser needs to watch.

  patchValueLocation(yourFormValues){
    this.form.patchValue(yourFormValues);
    this.createReference(this.formGroup.value)
    this.loading = false;
  }

  private createReference(obj: any){
    this.reference = JSON.stringify(obj)
  }

  ngOnInit() {
    this.form.valueChanges.subscribe(newValues=> {
      if(!this.loading){
        const hasChanges = !( JSON.stringify(newValues) === this.reference );
        this.dirty = hasChanges;
      }
    })
  }

You can listen to individual form controls too as seen in this document.

https://alligator.io/angular/reactive-forms-valuechanges

ngOnInit(): void {
  this.myForm.get('name').valueChanges.subscribe(val => {
    this.formattedMessage = `My name is ${val}.`;
  });
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.