3

There was lots to read about this particular error, as well as some solutions floating around that applied to the specific implementation it was addressing. I have no idea how it would apply to mine. I am changing the background color of a material expansion panel based on whether the FormGroup is valid. I have some checkbox form controls on some of the FormGroups that toggle the visibility of other textfields, and also their validators. Up until recently (perhaps upon updating from 4.4.3 to 4.4.6) this worked fine. Now, however, toggling validation on a control in a previously valid formgroup throws the expression has changed after it has been checked error.

    <md-expansion-panel [expanded]="step===1" (opened)="setStep(1)" [ngStyle]="{'background': changeForm.get('changeOverviewFG').valid && changeForm.get('changeOverviewFG').touched ?'#cffccf' :'#fff'}">
    <div class="row">
        <div class="col-xs-12 col-sm-12">
            <h4>Type of Change</h4>
        </div>
        <div class="col-xs-12 col-sm-6">
            <input type="checkbox" formControlName="srvCheck" (click)="setValidator(changeForm.get('changeOverviewFG.srvCheck'),[changeForm.get('changeOverviewFG.srvPackage')])">SRV Package
        </div>
   </div>
   <div class="row">
         <div *ngIf="changeForm.get('changeOverviewFG.srvCheck').value">
              <div class="form-group" [ngClass]="{'td-group-error': displayMessage.srvPackage }">
                    <textarea class="form-control" rows="2" formControlName="srvPackage" placeholder="Description/Name if known" style="width:100%"> </textarea>
                    <div class="error-block" *ngIf="displayMessage.srvPackage" role="alert" style="color: #ae0101">
                          <strong>!</strong> {{displayMessage.srvPackage}}
                    </div>
              </div>
         </div>
   </div>

So my setvalidator calls on my checkboxes call the following function from my component class

setValidator(c: FormControl, d: [FormControl]) {
    if (!c.value) {
      d.forEach(element => {
        element.setValidators(Validators.required);
      });

    } else {
      d.forEach(element => {
        element.clearValidators();
      });
    }
  }

The error for this section occurs on the very first line with the [ngStyle] that changes the background color depending on whether the formGroup is valid. Can anyone tell me how I can properly handle how it's checking for changes?

One of the references I was trying to make sense of was this one but I don't know how it would work with my instance concerning [ngStyle] in the template.

David
  • 573
  • 7
  • 40
  • My apologies, I had two examples in there, I reduced it to just the one and removed irrelevant code like the header and title. I will take a look at stackblitz as well. – David Oct 30 '17 at 15:32
  • I appreciate you having a look, thank you. – David Oct 30 '17 at 15:42
  • Does this answer your question? [How to manage Angular2 "expression has changed after it was checked" exception when a component property depends on current datetime](https://stackoverflow.com/questions/39787038/how-to-manage-angular2-expression-has-changed-after-it-was-checked-exception-w) – luiscla27 Jan 12 '22 at 18:22

1 Answers1

0

I ended up figuring it out. My problem was twofold. One was my not properly clearing validators, which I remedied by calling updateValueAndValidity() after clearValidators() as demonstrated below

setValidator(c: FormControl, d: [FormControl]) {
if (!c.value) {
  d.forEach(element => {
    element.setValidators(Validators.required);
  });

} else {
  d.forEach(element => {
    element.clearValidators();
    element.updateValueAndValidity();
  });
}
}

Secondly, something about the [ngStyle] attribute and logic being in the template was causing the expression changed after checked error. I moved the logic to the ngAfterContentChecked lifecyle hook as demonstrated below.

  ngAfterContentChecked(): void {
if (this.changeForm.get('changeOverviewFG').valid && this.changeForm.get('changeOverviewFG').touched) {
  this.changeOverviewColor = '#cffccf';
} else {
  this.changeOverviewColor = '#fff';
}
}

And then changed the attribute tag to the following in the template

<md-expansion-panel class="changeOverviewFGpanel" [expanded]="step===1" (opened)="setStep(1)" [style.background]="changeOverviewColor">
David
  • 573
  • 7
  • 40