Chrillewoodz
Chrillewoodz

Reputation: 28368

Dynamic classname inside ngClass in angular 2

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?

Upvotes: 178

Views: 271535

Answers (10)

Mamadou Ouologuem
Mamadou Ouologuem

Reputation: 236

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>

Upvotes: 3

Kroksys
Kroksys

Reputation: 1001

This works perfectly!

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

Example:

<div [class.hide]="user.isPaid()"></div>

Upvotes: 8

Ankit Singh
Ankit Singh

Reputation: 24945

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

Upvotes: 274

Den Kerny
Den Kerny

Reputation: 621

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"

Upvotes: -1

perform3r
perform3r

Reputation: 91

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"

Upvotes: 9

Anthony Agbator
Anthony Agbator

Reputation: 508

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

Upvotes: 1

SHUBHASIS MAHATA
SHUBHASIS MAHATA

Reputation: 940

  <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>

Upvotes: 12

Dicekey
Dicekey

Reputation: 405

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 }" 

Upvotes: 3

ykadaru
ykadaru

Reputation: 1144

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.

Upvotes: 3

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 658057

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.

Upvotes: 23

Related Questions