1

When I try to use [ngClass] in my Angular application, I get the following error:

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngClass: undefined'.

It works when I call a change after I got the error, the issue seems to be during initialization.

Here is the HTML:

  <div class="switch-wrapper">
    <button [ngClass]="loginSelected ? 'selected' : ''" (click)="selectLogin()">
      Login
    </button>
    <button [ngClass]="signupSelected ? 'selected' : ''" (click)="selectSignup()">
      Signup
    </button>
  </div>

And here is the TS:

export class LoginComponent implements AfterContentInit {

  loginSelected = true;
  signupSelected = false;

  constructor(private cdRef: ChangeDetectorRef) {
  }

  ngAfterContentInit() {
    this.cdRef.detectChanges();
  }

  selectLogin() {
    this.loginSelected = true;
    this.signupSelected = false;
  }

  selectSignup() {
    this.loginSelected = false;
    this.signupSelected = true;
  }
}

This questions has been asked many times on here, but the suggested solutions don't seem to work for me. Things I've Tried:

  1. Not using the ChangeDetector.
  2. Doing changes and then calling .detechChanges().
  3. Calling .detechChanges() and then doing changes.
  4. Just initializing the values.
  5. Using ngOnInit and the different types of ngAfter***().
  6. Any combinations of the above.

If someone could help me, I'd greatly appreciate it. I know the error is probably on my part, and this is driving me nuts. Thanks!

TobiDevloft
  • 301
  • 3
  • 12
  • Please also show how `loginSelected` and `signupSelected` are modified in the code. – ConnorsFan Mar 11 '19 at 15:44
  • Added the missing logic! – TobiDevloft Mar 11 '19 at 15:47
  • I cannot reproduce the problem. See [this stackblitz](https://stackblitz.com/edit/angular-ozfvh7?file=src%2Fapp%2Fapp.component.html). – ConnorsFan Mar 11 '19 at 15:51
  • weird, no idea what the issue is. Thanks for trying! – TobiDevloft Mar 11 '19 at 16:02
  • The discussion in [this question](https://stackoverflow.com/q/45467881/1009922) may help you. – ConnorsFan Mar 11 '19 at 16:14
  • It did, thank you. The issue was that the component was appended to the dom in the ngOnInit of another component. Still, I don't understand why that would be an issue. Do you have an idea? – TobiDevloft Mar 11 '19 at 16:23
  • If you reproduce the problem in a stackblitz, we may see better what is going on. – ConnorsFan Mar 11 '19 at 16:25
  • This code is used as part of a modal, which is implemented with a custom modal and dom service. The issue probably lays there somewhere - even though everything else works as intended -, but it's too much code to reproduce in stacklitz. I resolved it for now, by not openening the modal in the ngOnInit. – TobiDevloft Mar 11 '19 at 16:36

3 Answers3

1

Just move the .detectChanges(); like this.

  selectLogin() {
    this.loginSelected = true;
    this.signupSelected = false;
    this.cdRef.detectChanges();
  }

  selectSignup() {
    this.loginSelected = false;
    this.signupSelected = true;
    this.cdRef.detectChanges();
  }
joka00
  • 2,357
  • 1
  • 10
  • 27
1

I think the best way to conditionally add class is like this:

<button [class.selected]="loginSelected" (click)="selectLogin()">
  Login
</button>
<button [class.selected]="signupSelected" (click)="selectSignup()">
  Signup
</button>

Also it is a lot cleaner. and you don't need change detection code, angular does that automatically.

0

It seems like the issue was appending the Component to the Dom via logic in the ngOnInit of another component. I will edit this when I understand why this is.

TobiDevloft
  • 301
  • 3
  • 12