RxJS icon Launch Deal: Get $100 off the RxJS Kickstart Bundle now!

RxJS Masterclass is here. 2-course bundle - buy now (discount applied at checkout).

days
hours
mins
secs

Angular Classes with NgClass

Feb 29, 2020 5 mins read

Angular post
Angular icon

Want to level up your Angular skills? Who doesn't. Here's what you need to know

Show Me View Angular courses

Let’s take a dive into Angular’s NgClass and master the syntax, whilst also learning about the native DOM API for class manipulation - an important feat before diving into the framework’s implementation.

With Angular, we have a few approaches to add, remove or even toggle a class. We can choose to change single class and bind to a property, or we can use the awesome NgClass directive from Angular to give us a powerful templating tool.

In this post, we’ll explore class bindings and also Angular’s NgClass directive (plus all the syntaxes and also some best practice ideas)!

It’s a frequent requirement to add some kind of “state” to the DOM, typically via classes. Open and closed, for example.

Let’s explore some quick and easy options we have with Angular.

Property Binding with className

Before we jump into NgClass, let’s explore some sugar syntax that’s simple, yet effective. When working with a single class name, I much prefer and advocate this approach over diving into NgClass - it’s faster to work with and I find it’s more descriptive when reading any existing code.

In good old JavaScript DOM, we have a className property available on DOM elements:

const div = document.querySelector('div');
div.className = 'active';
console.log(div.className); // 'active'

Nice and easy, and with this knowledge we can begin to utilise NgClass effectively.

Above, we’re setting a JavaScript property on a DOM Node.

In in Angular we work with templates and bindings - not DOM APIs such as querySelector. Angular cleverly binds to properties through its template syntax - not an attribute (unless you’d like just an attribute).

To bind to the className property using Angular, we’ll need to using the [] binding syntax to directly bind to a property:

<div [className]="'active'"></div>

Angular will then lookup the JavaScript property of className and bind our expression to it (in the above case, it’s a String value but this could also be a variable defined in the Component which holds some data).

Due to Angular’s clever binding syntax, we can mix and match property binding with JavaScript-like expressions, known as just “expressions” in Angular.

For example, we could use the ternary statement to conditionally apply a className based on the value of condition. If it’s a truthy value 'active' will be added, otherwise 'inactive' would be displayed:

<div [className]="condition ? 'active' : 'inactive'"></div>

Bear in mind, we cannot do this:

<!-- if the condition is false, we will end up with class="false" -->
<div [className]="condition && 'active'"></div>

We want to avoid this, and supply a class at all times, unless we don’t want that behaviour. So what about just one class?

Property binding with “class”

Angular has a shorthand syntax for supplying a class, instead of using className - but also with some additional super powers:

<div [class.active]="condition"></div>

When our condition variable evaluates to true, the class of active will be added. What an amazing syntax!

When false, active is then removed. This is really nice, clean and concise!

What about more complex classes, perhaps using the BEM (Block-Element-Modifier) syntax?

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

That’s all we need. Thankfully we don’t need to supply the is-active inside a string, which you might expect when using a dash. The same applies with further BEM syntax, such as underscores and more dashes.

So now we’ve been primed with JavaScript DOM knowledge on classes, and also looked at the class property in Angular, it’s time for some NgClass - more flexible approach (and one we should use when we need multiple classes).

Angular’s NgClass Directive

We should use NgClass when we’re expecting multiple classes to be potentially added.

The basic syntax of NgClass:

string | string[] | Set<string> | { [klass: string]: any }

This means we can supply single strings, arrays of strings, Sets, and object literals. Really, we just care about the object literal approach, strings and string arrays allow us to set classes, but not remove them - because there’s no conditional data powering their existence:

<div [ngClass]="'active'"></div>
<div [ngClass]="['active', 'open']"></div>

So, let’s investigate object literals with NgClass:

<div [ngClass]="{
  active: condition
}">
</div>

Just like our previous example with [class.active] - this essentially does the same thing.

Note, however, we cannot do this (note the dash, not being a string value):

<!-- errors -->
<div [ngClass]="{
  is-active: condition
}">
</div>

Why? Because this is an object literal, keys cannot be set using dashes without using a string syntax (so yes, it’s more JavaScript syntax here):

<!-- works -->
<div [ngClass]="{
  'is-active': condition
}">
</div>

If you need a more complex CSS class, such as BEM syntax, use a string! If you like, keep your keys consistent and always use a string even if it’s not needed. This may be a sensible styling choice within your team, and one I’d certainly go for as I’m an avid fan of BEM.

Multiple Classes with NgClass

So far we’ve covered adding and removing single classes with NgClass, so let’s look at a more ideal solution with multiple classes.

It’s also worth noting that the condition we supply as the value of the object literal key, will be evaluated. This means we can use ternary statements (? :), negation expressions (!) or logical expressions (&&), for example:

<div [ngClass]="{
  'is-active': condition,
  'is-inactive': !condition,
  'is-focused': condition && anotherCondition,
}">
</div>

And there you have the majority of use cases you’ll ever need when it comes to NgClass. For readability purposes, I would encourage you to bump conditions onto new lines as demonstrated above. It’s easy to scan, read, and evaluate what’s happening in your codebase, and your fellow team-mates will thank you for your well considered approach ;)

Mixing class and NgClass

When it comes to keeping your codebase consistent, which is a must, choose one approach and stick with it.

It might be you and your team prefer to use [class.foo] style syntax for the majority of use cases, and simply adopt NgClass when introducing more complex scenarios. Or, you may favour just using NgClass - but the rule is pick one, be consistent and maintainable.

To learn more techniques, best practices and real-world expert knowledge I’d highly recommend checking out my Angular courses - they will guide you through your journey to mastering Angular to the fullest!

Love the post? Share it!

Lots of time and effort go into creating all our blogs, resources and demos, we'd love if you'd spare a moment to share this one!