title: Angular : Activate checkbox on some conditions throws ExpressionChangedAfterItHasBeenCheckedError
body: <p>I currently implement angular project which needs a term and conditions agreement. So I have created a scrollable div of 300 px in which I load the content from the database. We want to force the user to read all T&amp;C before activating the checkbox. </p>
  
  <p>It's working well when T&amp;C are heavy. When T&amp;C are light, the scrollable function is not called. So I want to initialize the disabled state of the checkbox at the end of the loading but angular throws <code>ExpressionChangedAfterItHasBeenCheckedError</code>.</p>
  
  <p>Here is the stackblitz of my project : <a href="https://stackblitz.com/edit/angular-b9p6rx" rel="nofollow noreferrer">https://stackblitz.com/edit/angular-b9p6rx</a></p>
  
  <p>I tried many solutions :</p>
  
  <ul>
  <li>replace the <code>*ngIf</code> by <code>[hidden]</code></li>
  <li>use a fonction to evaluate the state</li>
  <li>check in the <code>afterViewContentInit</code></li>
  <li>Use a setter on the <code>div</code> content</li>
  </ul>
  
  <p>I want to avoid the <code>setTimeout</code> call to evaluate the state.</p>
  
  <p>What solutions do you see ?</p>
  
  <p>Is there a better way to implement this function ?</p>
  
  <p>Thanks in advance. </p>
  
  <p><strong><em>app.component.html</em></strong></p>
  
  <pre><code>    &lt;div class="content-box" *ngIf="isNotUpToDateCGU"&gt;
      &lt;h1&gt;Terms and conditions&lt;/h1&gt;
      &lt;span&gt;
          &lt;i&gt;{{agreementHeader1}}&lt;/i&gt;
      &lt;/span&gt;
      &lt;br&gt;
      &lt;div #cguContainer id="content" class="cgu-content" (scroll)="checkReading()" [innerHTML]="cguContent"&gt;&lt;/div&gt;
      &lt;div class="text-right"&gt;
          &lt;span&gt;I accept the terms and conditions&lt;/span&gt;
          &lt;p-checkbox [(ngModel)]="areCGUAccepted" binary="true" [disabled]="!hasContentBeenRead"&gt;&lt;/p-checkbox&gt;
      &lt;/div&gt;
      &lt;div class="text-right cgu-buttons"&gt;
          &lt;button type="button" class="btn btn-primary mx-2" &gt;Annuler&lt;/button&gt;
          &lt;button type="submit" class="btn btn-primary mx-2" [disabled]="!areCGUAccepted"&gt;Valider&lt;/button&gt;
      &lt;/div&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p><strong><em>app.component.ts</em></strong></p>
  
  <pre><code>export class AppComponent  {
    public agreementHeader1: string;
      public cguContent: string;
      public hasContentBeenRead: boolean = false;
      public areCGUAccepted: boolean = false;
      public isNotUpToDateCGU: boolean  = false;
  
      private cguContainerRef: ElementRef;
      @ViewChild('cguContainer') set controlElRef(elementRef: ElementRef) {
        if (elementRef) {
          this.cguContainerRef = elementRef;
          this.checkReading();
        }
      }
  
      constructor(
          private confService: ConfigurationService,
      ) { }
  
      public ngOnInit(): void {
        this.confService.getConfiguration('./terms.json')
              .subscribe(result =&gt; {
  
                  this.agreementHeader1 = 'You have to read all terms and conditions to accept them';
  
                  // !!!!!!! invert the two lines to test with big terms
                  // this.cguContent = result.bigTerms;
                  this.cguContent = result.littleTerms;
  
                  this.isNotUpToDateCGU = true; // load template
              });
      }
  
      public checkReading(): void {
  
          let element = this.cguContainerRef.nativeElement;
  
          // height of the div in css =&gt; height: 300px
          if (element.scrollHeight - element.scrollTop &lt; 301) {
              this.hasContentBeenRead = true;
          }
      }
  }
  </code></pre>