Difference between [ngClass] vs [class] binding
Q

9

97

What is the difference in Angular 2 between the following snippets:

<div [class.extra-sparkle]="isDelightful">
<div [ngClass]="{'extra-sparkle': isDelightful}">
Qualify answered 26/7, 2017 at 8:33 Comment(2)
It's worth noting that there is also a [className] property binding which can be used like so <div [className]="isDelightful ? 'extra-sparkle'">.Heptagon
Would you not need to complete the ternary with a :? Otherwise using && in place of the ? will be validQualify
A
84

This is special Angular binding syntax

<div [class.extra-sparkle]="isDelightful">

This is part of the Angular compiler and you can't build a custom binding variant following this binding style. The only supported are [class.xxx]="...", [style.xxx]="...", and [attr.xxx]="..."

ngClass is a normal Angular directive like you can build it yourself

<div [ngClass]="{'extra-sparkle': isDelightful}">

ngClass is more powerful. It allows you to bind a string of classes, an array of strings, or an object like in your example.

Ambriz answered 26/7, 2017 at 8:35 Comment(8)
Ah so in the docs when it says <div [attr.role]="myAriaRole"> it's binding the role attribute of the div not the role attribute of an object called attr from the controller. Makes sense, thanksQualify
attr.foo is for binding to attributes instead of properties. See #6004319. @Input() of Angular components and directives are treated as properties. Binding to attributes only supports string values, attributes support any kind of value. If there is an @Input() with a matching name used to the bind to the attribute, the value will also be passed to the @Input(). If you bind to an elements native attribute (like for in <label> , then the browser has its own implementation how the value is reflected to the property.Teacake
Thanks, although I think "Binding to attributes only supports string values, attributes support any kind of value." may have been mis-typed?Qualify
@BenTaliadoros thanks, you're right. It should be "properties support any kind of value".Teacake
So, which one is better in this scenario for performance? Doesn't matter which one you use?Clamatorial
Binding to class is probably faster, because it just assigns the whole string. ngClass has to watch the expression and might have to add/remove individual classes when the expression changes. It's usually better to use ngClass anyway, because binding to class just overwrites classes that might be set from elsewhere and the performance argument is probably just a premature optimization case.Teacake
well, in fact [class]="{'extra-sparkle': isDelightful}" is also working...Sectarianize
@romanm Yes, that should work as well. The difference is that your version will override classes added by other means, because [class] is the full HTML class="xxx" property/attribute, while the variants in my answer add/remove only the class extra-sparkle and leave other classes as is.Teacake
M
34

The above two lines of code is with respect to CSS class binding in Angular. There are basically 2-3 ways you can bind css class to angular components.

You provide a class name with class.className between brackets in your templates and then an expression on the right that should evaluate to true or false to determine if the class should be applied. That is the below one where extra-sparkle(key) is the css class and isDelightful(value).

<div [class.extra-sparkle]="isDelightful">

When multiple classes should potentially be added, the NgClass directive comes in really handy. NgClass should receive an object with class names as keys and expressions that evaluate to true or false. extra-sparkle is the key and isDelightful is the value (boolean).

<div [ngClass]="{'extra-sparkle': isDelightful}">

Now along with extra sparkle, you can glitter your div also.

<div [ngClass]="{'extra-sparkle': isDelightful,'extra-glitter':isGlitter}">

or

export class AppComponent {
    isDelightful: boolean = true;
    isGlitter:  boolean = true;
    
    get sparkleGlitter()
    {
        let classes = {
            extra-sparkle: this.isDelightful,
            extra-glitter: this.isGlitter
        };
        return classes;
    }
}

<div [ngClass]='sparkleGlitter'>

For ngClass, you can have conditional ternary operators too.

Misestimate answered 21/5, 2018 at 3:17 Comment(0)
B
19

In the current version of Angular following syntax is also working fine:

[class]="{toggled: sidebarActive, test: true,test1: sidebarActive}

So to my understanding, there is no difference between using ngClass and [class] binding?

Example

Bonds answered 30/11, 2020 at 22:52 Comment(4)
Are you asking a question?Tutor
I'm answering the question but it's pretty old. The only difference I was able to find was that ngClass can handle multiple class binding whilst [class] binding can handle only one but that seems this is not true. So my only question is - is there any difference?Omniscient
You're not suppose to ask a question in the Answer box :) See the tour and how to answer. But you're saying that half of your post is an answer.. and the other is a question.Tutor
the great part of my answer is actually answering the question in regards to the new version of angular. So as I said before, I'm not asking the question, the "question" I've asked is rather rhetorical and axillary.Omniscient
A
15

Using [ngClass] you're able to apply multiple classes in a really convenient way. You can even apply a function that will return an object of classes. [class. makes you able to apply only one class (of course you can use class. a few times but it looks really bad).

Acquit answered 26/7, 2017 at 8:36 Comment(0)
J
8

In [ngClass] you can add one of two different classes like this:

<div [ngClass]="a === b ? 'class1' : 'class2'">
Jollanta answered 26/7, 2017 at 8:41 Comment(3)
You could also do this <div class="{{a === b ? 'class1' : 'class2'}}">Qualify
This behavior in the answer does not distinguish [ngClass]. You can do the same with [class].Cauterant
like already mentioned the same can be done with [class] please update your answer.Mastership
D
8

After going through multiple answers, I thought to add my view as this might be helpful.

So, Angular is planning to remove [ngClass] and [ngStyle] directives in their future releases.

As of now (Angular-v13), [class] binding supports to add multiple css classes. Though there are some feature gaps when compared with [ngClass]. You can check this - https://github.com/angular/angular/issues/40623

[ngClass]

<p [ngClass] = “‘addGreen’”> Hello World </p> 
<p [ngClass] = “[‘addGreen’, ‘addFont’, ‘addBg’]”> Hello World </p>
<p [ngClass] = “{ addGreen: true, addBg: true, addFont: false }”> Hello World </p> 
<p [ngClass] = “{ addGreen addBg: true, addFont: false}”> Hello World </p>

[class]

<p [class] = “‘addGreen’”> Hello World </p> 
<p [class] = “[‘addGreen’, ‘addFont’, ‘addBg’]”> Hello World </p>
<p [class] = “{ addGreen: true, addBg: true, addFont: false }”> Hello World </p> 

Note : The below way of adding the multiple classes is not possible

<p [class] = “{ addGreen addBg: true, addFont: false}”> Hello World

Dyeing answered 19/2, 2022 at 12:30 Comment(0)
Q
0

Yes, with help of class binding ([class]) also we can attach multiple css classes with latest versions. ex:[class]='{object with key as class name and value as true/false}' same like [ngClass] so..there is no difference between [class] binding and inbuilt [ngClass] directive

Quicksand answered 10/5, 2021 at 6:22 Comment(0)
A
0

No one has mentioned that if you use both [class] and [ngClass] bindings some confusion can occur once you try to pass some class string to [class] that is 'registered' by [ngClass]. They can compete.

E.g. this will not assign the 'd-flex' class value to the [class] binding as long as an [ngClass] condition which is associated with this class has evaluates to true:

component.html

<div [ngClass]="{'d-flex': falseCondition}" [class]="getClassBasedOnCondition()">

component.ts

public getClassBasedOnCondition(): string {
    return trueCondition ? 'd-flex' : '';
}

You can use [class.] instead of [ngClass] to avoid such behavior, as long as you don't have multiple classnames there, such as [ngClass]="{'d-flex p-1': condition}"

Affinitive answered 29/5, 2021 at 19:48 Comment(1)
To add to this answer, one can consider styling precedences from angular.io/guide/style-precedence#style-precedence. Because ngClass (and the same should apply to ngStyle) is a directive, and atribute bindings have precedence over stylings made by directives, [class]="classExpr" or [class.klass]="expr" should override ngClass.Detect
L
0

[Class] works similar to [ngClass] after Angular 13+, minor difference is that [Class] is an expression attribute where it will override the [ngClass] directive.

Eg:

<p [ngClass]="{'redfont':true, 'backgroundClr':true}" [class.whitefont]="applyWhiteColor">Hello world</p>

Component.ts:

applyWhiteColor: boolean = true;

Component.css:

.redfont{
    color: red;
}

.whitefont{
    color: #fff;
}

.backgroundClr{
    background-color: green;
}
Lucindalucine answered 16/1 at 2:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.