170

I need to interpolate a value inside of an ngClass expression but I can't get it to work.

I tried these solution which are the only ones that makes sense to me, these two fails with the interpolation:

<button [ngClass]="{'{{namespace}}-mybutton': type === 'mybutton'}"></button>
<button [ngClass]="{namespace + '-mybutton': type === 'mybutton'}"></button>

This one works with the interpolation but fails with the dynamically added class because the entire string gets added as a class:

<button ngClass="{'{{namespace}}-mybutton': type === 'mybutton'}"></button>

So my question is how do you use dynamic classnames in ngClass like this?

Chrillewoodz
  • 27,055
  • 21
  • 92
  • 175

10 Answers10

264

Try

<button [ngClass]="type === 'mybutton' ? namespace + '-mybutton' : ''"></button>

instead.

or

<button [ngClass]="[type === 'mybutton' ? namespace + '-mybutton' : '']"></button>

or even

<button class="{{type === 'mybutton' ? namespace + '-mybutton' : ''}}"></button>

will work but extra benefit of using ngClass is that it does not overwrite other classes that are added by any other method( eg: [class.xyz] directive or class attribute, etc.) as class does.

Angular 9 Update

The new compiler, Ivy, brings more clarity and predictability to what happens when there are different types of class-bindings on the same element. Read More about it here.


ngClass takes three types of input

  • Object: each key corresponds to a CSS class name, you can't have dynamic keys, because key 'key' "key" are all same, and [key] is not supported AFAIK.
  • Array: can only contain list of classes, no conditions, although ternary operator works
  • String/ expression: just like normal class attribute
Mordred
  • 3,734
  • 3
  • 36
  • 55
Ankit Singh
  • 24,525
  • 11
  • 66
  • 89
  • How can I write a css class inside .scss file dynamically. For ex: I have written a "overlay" class. This class being used in a div which is getting cerated inside a loop. There will be multiple divs using this overlay class. I want to attach loop index to this class like overlay-1, overlay-2 etc. Is it possible? – sandeep Jul 17 '20 at 08:03
23

This one should work

<button [ngClass]="{[namespace + '-mybutton']: type === 'mybutton'}"></button>

but Angular throws on this syntax. I'd consider this a bug. See also https://stackoverflow.com/a/36024066/217408

The others are invalid. You can't use [] together with {{}}. Either one or the other. {{}} binds the result stringified which doesn't lead to the desired result in this case because an object needs to be passed to ngClass.

Plunker example

As workaround the syntax shown by @A_Sing or

<button [ngClass]="type === 'mybutton' ? namespace + '-mybutton' : ''"></button>

can be used.

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
11
  <div *ngFor="let celeb of singers">
  <p [ngClass]="{
    'text-success':celeb.country === 'USA',
    'text-secondary':celeb.country === 'Canada',
    'text-danger':celeb.country === 'Puorto Rico',
    'text-info':celeb.country === 'India'
  }">{{ celeb.artist }} ({{ celeb.country }})
</p>
</div>
SHUBHASIS MAHATA
  • 873
  • 7
  • 12
7

Is basically duplication of the other answers - but I didn't get it completely. maybe someone will finally understand it with this example now.

[ngClass]="['svg-icon', 'recolor-' + recolor, size ? 'size-' + size : '']"

will result for e.g. in

class="svg-icon recolor-red size-m"
perform3r
  • 71
  • 1
  • 2
6

This works perfectly!

<div [class.any-class]="condition"></div>

Example:

<div [class.hide]="user.isPaid()"></div>
Dharman
  • 30,962
  • 25
  • 85
  • 135
Kroksys
  • 759
  • 10
  • 15
3

Here's an example of something I'm doing for multiple classes with multiple conditions:

[ngClass]="[variableInComponent || !anotherVariableInComponent ? classes.icon.large : classes.icon.small, editing ? classes.icon.editing : '']"

where:
classes is an object containing strings of various classnames. e.g. class.icon.large = "app__icon--large"

It's dynamic! Updates as the conditions update.

ykadaru
  • 1,108
  • 2
  • 16
  • 32
3

i want to mention some important point to bare in mind while implementing class binding.

    [ngClass] = "{
    'badge-secondary': somevariable  === value1,
    'badge-danger': somevariable  === value1,
    'badge-warning': somevariable  === value1,
    'badge-warning': somevariable  === value1,
    'badge-success': somevariable  === value1 }" 

class here is not binding correctly because one condition is to be met, whereas you have two identical classes 'badge-warning' that may have two different condition. To correct this

 [ngClass] = "{
    'badge-secondary': somevariable === value1,
    'badge-danger': somevariable  === value1,
    'badge-warning': somevariable  === value1 || somevariable  === value1, 
    'badge-success': somevariable  === value1 }" 
Dicekey
  • 405
  • 4
  • 12
3

The easiest way might be to define a getter in your component.ts. Most importantly, it's one of the recommendations in Angular coding style

// in your component.ts
get buttonClasses() {
    return { [`${this.namespace}-mybutton`]: this.type === 'mybutton' }
}
<!-- in your component.html -->
<button [ngClass]="buttonClasses"></button>
0

You can use <i [className]="'fa fa-' + data?.icon"> </i>

Anthony Agbator
  • 488
  • 3
  • 6
  • 3
    While this code snippet may be the solution, [including an explanation](//meta.stackexchange.com/questions/114762/explaining-entirely-‌​code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. – f.khantsis Mar 30 '20 at 15:40
-1

more elegant solution is to use && (using NgFor and its first, its free to use ur own matching tho):

    <div 
        *ngFor="let day of days;
                let first = first;"
        class="day"
        [ngClass]="first && ('day--' + day)"
    </div>

will turn out as:

class="day day--monday"
Den Kerny
  • 562
  • 10
  • 18