ngClass does not switch value when using object in component

117 Views Asked by At

When I use the following code to switch the class everything works fine

<p [ngClass]="idPresent ? 'alert alert-success' : 'alert alert-danger'">
  Working
</p>

On changing the value of IdPresent in the component, I can see the appropriate class being applied,

but when I use an object in the component for the same purpose it only works if idPresent is false. When I set the idPresent to true, the following code does not apply the appropriate class.

<p [ngClass]="idValueClass">
   Not working
</p>
public idPresent = false;
 
public idValueClass = {
  "alert alert-success" : this.idPresent,
  "alert alert-danger"  : !this.idPresent
};

Can someone help me figure out what am I doing wrong?

Update:

I am changing the value of idPresent after receiving response from REST API call

 ngOnInit(): void {
 this.http.get('http://localhost:8083/v1/uniqueid', {
  headers: {'Authorization':'Basic dXNlcjpwYXNzd29yZA=='}
 })
 .subscribe(response => {
    if(response) {
      console.log(response)
       this.serverId = response;
       this.idPresent = true;
    } else {
       this.idPresent = false;
    }
    console.log("idPresent : " + this.idPresent)
 })

}

After receiving response from server, I can see updated value in console.

3

There are 3 best solutions below

2
On BEST ANSWER

To complementary @Yong Shun, in Angular 16 and 17 we can use signal

We can define:

  public idPresent = signal(false);

  public idValueClass = computed(() => ({
    alert: true,
    'alert-success': this.idPresent(),
    'alert-danger': !this.idPresent(),
  }));

  onClick() {
    this.idPresent.update(value => !value);
  }

Be carefull, the .html we need reemplace idPresent by idPresent() and idValueClass by idValueClass()

  <p [ngClass]="idValueClass()">
    Not working
  </p>
  Current idPresent: {{ idPresent() }}

A stackblitz full stolen from the Yong Shun stackblitz.

NOTE: See that in the stackblitz I use changeDetection:ChangeDetectionStrategy.OnPush, but, when a signal is update, Angular update the entire view

6
On

I believe that you mentioned the issue in which the "alert" class is removed.

From the documentation,

Object - keys are CSS classes that get added when the expression given in the value evaluates to a truthy value, otherwise they are removed.

This results that the last "alert" was false and will be removed from the class.

Modify the idValueClass as below:

public idValueClass = {
  alert: true,
  'alert-success': this.idPresent,
  'alert-danger': !this.idPresent,
};

Demo @ StackBlitz


Updated

As raised by @Eliseo, if you have a button or logic to update the idPresent, the idValueClass will not automatically reflect the latest value.

You need a trigger/change event to overwrite the idValueClass.

<button class="btn btn-primary" (click)="onClick()">Update</button>
onClick() {
  this.idPresent = !this.idPresent;
  this.idValueClass = {
    alert: true,
    'alert-success': this.idPresent,
    'alert-danger': !this.idPresent,
  };
}

Or implement a getter for idValueClass (However it is not a good practice, Refer: Getter and setter in templates is a bad idea)

0
On

i ever this problem before, i ever any key name class can be hidden like "success", "alert", "warning" etc with same case before. i try to make it single name class (alert-success") , not mutiple class ("alert alert-success") .

you can try this code as below =

enter code here

public idValueClass = {
  'alert': true,
  'alert-success': this.idPresent,
  'alert-danger': !this.idPresent,
};

i more suggestion condition on ngClass use tenary then get value on .ts

idValueClass() {
  return this.idValueClass ? 'alert alert-success' : 'alert alert-danger'
};