Angular Classes with NgClass blog post

Angular Classes with NgClass

Todd Motto

29 Aug, 2019

Angular

5 minutes read

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

In this post, we’ll explore class bindings, and also Angular’s NgClass directive, 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. 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 single classes, 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.

So, what does it look like?

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

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

Nice and easy. Remember, this is a property we’re setting. But, in Angular we’re working with templates and bindings – not DOM APIs such as querySelector.

In Angular, we bind to properties, not attribute. Which means we can turn this knowledge into:

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

Angular will then lookup the JavaScript property of className and bind our expression to it.

It might be that we wish to provide a conditional to our className and use a ternary syntax:

<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, which I absolutely love:

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

When our condition evaluates to true, the class of active will be added. 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.

About the author

Todd Motto profile picture

Todd Motto

GDE Google Developer Expert

Todd is the Founder of Ultimate Courses. With a passion for Angular, TypeScript and JavaScript, Todd leads the online courses creation and has written hundreds of articles on front-end web development and beyond. He specialises in breaking down complex topics and understands the critical mission of learning new technology fast, comprehensively and the right way.

Love the post? Share it!

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

Explore our Angular courses

Get started today and join over 50,000 developers.