Check if Reactive form value is changed from initial

Viewed 15958

I have a reactive form with 3 controls in it, I want to detect changes of the form. I have created a value change method of the form and subscribed to it but. Right now every time any of it's control value is changing the event is emitting.

If user has added any value to ant of this 3 controls and trying to exit the page, then I want to promt a modal that there is unsaved changes in the form.

How can I be able to check the emitted value on change of the form is different than it's initial value?

public createGroupForm : FormGroup;

ngOnInit() {
  this.createGroupForm = this._formBuilder.group({
      groupName: new FormControl("", [Validators.required]),
      groupPrivacy: new FormControl(null, [Validators.required]),
      groupTagline: new FormControl('')
  });

  this.onCreateGroupFormValueChange();
}


onCreateGroupFormValueChange(){
    this.createGroupForm.valueChanges.subscribe(value => {
      console.log(value);
      //emitting every time if any control value is changed
    });
}
4 Answers

you must each time your subscribe is emitted check the form value with initial value and use hasChange when ever you want

public createGroupForm : FormGroup;
hasChange: boolean = false;

ngOnInit() {
  this.createGroupForm = this._formBuilder.group({
      groupName: new FormControl("", [Validators.required]),
      groupPrivacy: new FormControl(null, [Validators.required]),
      groupTagline: new FormControl('')
  });

  this.onCreateGroupFormValueChange();
}


onCreateGroupFormValueChange(){
    const initialValue = this.createGroupForm.value
    this.createGroupForm.valueChanges.subscribe(value => {
      this.hasChange = Object.keys(initialValue).some(key => this.form.value[key] != 
                        initialValue[key])
    });
}

I think you should use ngOnDestroy life cycle hook method and then in that method check if the current value is different from initial value , then open the modal ....

@Component({ selector: 'my-cmp', template: `...` })
class MyComponent implements OnDestroy {
    public createGroupForm: FormGroup;
    public initalValues;

    ngOnInit() {
        this.createGroupForm = this._formBuilder.group({
            groupName: new FormControl("", [Validators.required]),
            groupPrivacy: new FormControl(null, [Validators.required]),
            groupTagline: new FormControl('')
        });
        this.initalValues = this.createGroupForm.value;
    }
    ngOnDestroy() {
        if (this.initalValues != this.createGroupForm.value) {
            //open modal
        }
    }
}

You can use rxjs operators to check values.

 import { FormGroup, FormBuilder, Validators, FormControl, FormArray, NgForm } from '@angular/forms';  
import { pairwise, startWith } from 'rxjs/operators';

this.createGroupForm.valueChanges
      .pipe(startWith(''), pairwise())
      .subscribe(([prev, cur]) => {
        console.log('example 1 prev val', prev);
        console.log('example 1 cur val', cur);
        console.log('---');

        if (confirm('value will be changed')) {
          console.log('value changed')
        } else {
          console.log('value not changed')
        }

You can use the dirty check when exiting the page like this

if(this.createGroupForm.get('groupName').dirty || 
 this.createGroupForm.get('groupPrivacy').dirty || 
 this.createGroupForm.get('groupTagline').dirty) {
   // make an alert for unsaved changes
}
Related