Angular Mastery: NgClass & NgStyle
Mastering the Fundamentals of Angular Template Syntax: Part 2
AngularInDepth is moving away from Medium. More recent articles are hosted on the new platform inDepth.dev. Thanks for being part of indepth movement!
Source Code: StackBlitz 🚀
Article Goal: Learn about Angular’s NgClass & NgStyle Directives.
Article Topics (What We’ll Learn):
- Discuss the Syntax and Semantics of NgClass & NgStyle
- Explore the Angular Source Code and see how NgClass & NgStyle work under the hood
- Use custom examples and cheat sheets to develop a better understanding of how to use NgClass and NgStyle
Overview
NgClass & NgStyle are Angular Directives that allow us to conditionally apply one-to-many classes/styles to an element. This provides a convenient way to work with multiple classes or styles at once and apply them conditionally; compared to their alternatives:
Native style and class attributes apply one-to-many classes/styles statically.
Angular’s class and style bindings only allow a single class or style to be conditionally applied at a time.
When determining when to use NgClass and NgStyle over Angular’s class and style bindings or the native attributes; consider:
- Am I applying classes/styles conditionally (dynamically) or statically?
- Am I applying one or many classes/styles?
Combining NgStyle and NgClass Directives with our knowledge of Angular Template Syntax, we can marry conditional styling with Angular’s Property & Event Binding.
Now that we have an understanding of why and when we would use them, let’s break down the two Angular Directives.
NgClass
Syntax
NgClass can receive input via inline declarations, or a property/method from our TypeScript class. This can make the syntax feel more convoluted than it really is. Ultimately, NgClass can take the following as input:
- A space-delimited String
[ngClass]="is-info is-item has-border"
- An Array of Strings
[ngClass]="['is-info', 'is-item', 'has-border'"]
- An Object
[ngClass]="{'is-info': true, 'is-item': true}
All of the above examples are inline and could be replaced with a Typescript property/method as long as the expression returns valid input:
export class MyComponentClass {
myStringProperty = "is-info is-item has-border";
myArrayProperty = ['is-info', 'is-item', 'has-border'];
myObjectProperty = {'is-info': true, 'is-item': true};
}
[ngClass]="myStringProperty"
[ngClass]="myArrayProperty"
[ngClass]="myObjectProperty"
Ternary statements are valid input, as long as they return a valid string, array, or object.
For example:
[ngClass]="name === 'erxk' ? 'is-author' : 'is-reader'
Under the Hood
For context, an example:
Key takeaways from our example code:
- Our
button
element has the NgClass Directive applied to it - Our NgClass input is
classStyler
from our Typescript Class.classStyler
evaluates to a valid object expression. - The properties on
classStyler
match the names of our CSS Classes. - NgClass will append classes, not overwrite. Our button will still have
class="big-font”
applied to it. - Updating the CSS classes on our HTML Element in our Typescript Class.
This way of leveraging TypeScript/JavaScript to update our CSS conditionally; starts to feel like utilizing the element.classList.add
and element.classList.remove
methods in Vanilla JavaScript:
updateButtonClass() {
const button = document.querySelector('button');
button.classList.add('info');
}
This is similar to what NgClass is doing under the hood. Looking at the source code for NgClass, it does all the heavy lifting and then invokes toggleClass()
.
Snippet below is context for the next snippet, we don’t have to worry about understanding it all.
If we look at the implementation of toggleClass()
, we can see that ultimately NgClass is simply using Angular’s Renderer2
to addClass()
or removeClass()
from our nativeElement
(The element with NgClass on it).
Note, this underlying implementation is the same whether we use NgClass with Typescript properties/methods or write expressions inline in our HTML.
Key Points
- We can pass a Typescript property/method or write an expression inline to our NgClass Directive
- NgClass can take a String, Array of Strings, or Object Expression as input.
- Under the hood, NgClass is adding/removing classes via
Renderer2
addClass()
andremoveClass()
- NgClass appends, it does not overwrite.
NgStyle
NgClass and NgStyle share a significant amount of functionality and behavior. The key difference is:
- NgStyle takes a key-value pair object as input.
- NgStyle applies styles and not classes.
- NgStyle will overwrite styles defined by the native style attribute.
Syntax
NgStyle takes a key-value pair object, where the key is a CSS style. An optional suffix can be added to the key, making keys such as this viable:
[ngStyle]="{font-size.px: 16}"
Instead of [ngStyle]="{font-size: 16px}"
Similar to NgClass, NgStyle can be passed input inline or use a Typescript property/method. [ngStyle]="myObjectExpressionProperty"
Under the Hood
For context, an example:
Key takeaways from our example code:
- NgStyle is being applied to our image
- Our NgStyle input is
styler
from our Typescript class.styler
evaluates to a valid object expression. - The properties in
styler
all evaluate to valid CSS styles - The
input
elements are updating values on ourstyler
property via Angular Event Binding.
If we take a look at the Angular source code, we can see that NgStyle uses a similar paradigm to NgClass. — NgStyle is a more straight-forward Directive; as it only accepts one type of input.
When Angular invokes _setStyle()
the AngularRenderer2
is used to invoke setStyle()
and removeStyle()
based on our input. Notice, we are setting the style, not appending. If we defined a style on our element using the native style attribute, it will be overwritten by NgStyle.
Key Takeaways
- NgStyle can accept a key-value pair as input, where the key is a valid CSS Style
- NgStyle can be passed input via inline or a Typescript property or method
- NgStyle under the hood utilizes Angular’s
Renderer2
to invokesetStyle()
andremoveStyle()
- NgStyle will overwrite existing styles on the element.
Conclusion
Thanks for reading! We’ve reviewed how to leverage the NgClass and NgStyle Angular Directives to achieve conditional styling with multiple classes/styles while utilizing Angular’s Property and Event Binding. We also looked at how NgClass and NgStyle are working under the hood and some example usages.
Series
Resources
- NgClass
- NgClass Source
- NgStyle
- NgStyle Source
- Class and Style Bindings
- Global Attribute Class
- Global Attribute Style
- Element Class List
☁️ Flotes — Try the demo, no login required. Or sign up for free. Flotes is how I take notes and learn efficiently, even when I’m busy.