Question
Angular ngClass Conditional Class Binding Explained
Question
I am using Angular to conditionally apply an active class to list items, but my template throws this error:
Cannot read property 'remove' of undefined at BrowserDomAdapter.removeClass
Here is the code:
<ol>
<li *ngClass="{ active: step === 'step1' }" (click)="step = 'step1'">Step1</li>
<li *ngClass="{ active: step === 'step2' }" (click)="step = 'step2'">Step2</li>
<li *ngClass="{ active: step === 'step3' }" (click)="step = 'step3'">Step3</li>
</ol>
What is wrong with this Angular code, and how should conditional class binding be written correctly?
Short Answer
By the end of this page, you will understand how Angular conditional class binding works, when to use ngClass versus [class.className], and why using the wrong binding syntax can cause runtime errors in templates.
Concept
Angular lets you add or remove CSS classes dynamically based on component state. This is called conditional class binding.
In Angular, ngClass is a directive, not a structural directive. That means it should be used like a normal property binding:
<li [ngClass]="{ active: condition }"></li>
A common mistake is to write *ngClass instead of [ngClass].
<li *ngClass="{ active: condition }"></li>
The * prefix is only for structural directives such as:
*ngIf*ngFor*ngSwitchCase
Structural directives change the DOM structure by creating or removing elements. ngClass does not create or remove elements. It only changes the classes on an existing element.
Because of that, Angular expects different behavior when it sees . Using makes Angular treat it like a structural directive, which leads to incorrect internal handling and can cause runtime errors like the one shown.
Mental Model
Think of an HTML element like a box that already exists on the page.
- A structural directive with
*decides whether the box exists at all. - A class binding decides what label or color sticker gets attached to that box.
So:
*ngIf= create or remove the box[ngClass]= keep the box, but change its CSS classes
Using *ngClass is like telling Angular: “Treat this class change like element creation logic.” That confuses Angular because ngClass is not built for that job.
Syntax and Examples
The correct syntax for conditional classes in Angular is:
<li [ngClass]="{ active: step === 'step1' }">Step 1</li>
You can also use direct class binding for a single class:
<li [class.active]="step === 'step1'">Step 1</li>
Corrected version of your example
<ol>
<li [ngClass]="{ active: step === 'step1' }" (click)="step = 'step1'">Step1</li>
<li [ngClass]="{ active: step === 'step2' }" (click)="step = 'step2'">Step2</li>
<li [ngClass]="{ active: step === 'step3' }" (click)="step = 'step3'">Step3</li>
Step by Step Execution
Consider this template:
<li [class.active]="step === 'step2'" (click)="step = 'step2'">Step2</li>
And this component state:
step = 'step1';
What happens step by step
-
Angular renders the
<li>element. -
It checks the expression:
step === 'step2' -
Since
stepis currently'step1', the result isfalse. -
Angular does not add the
activeclass. -
The user clicks
Step2. -
The click handler runs:
step =
Real World Use Cases
Conditional class binding is used in many common Angular interfaces.
Navigation menus
Highlight the current page or selected section.
<a [class.active]="currentPage === 'home'">Home</a>
Tab components
Show which tab is selected.
<button [class.active]="selectedTab === 'profile'">Profile</button>
Form validation
Mark invalid inputs visually.
<input [class.invalid]="emailTouched && !emailValid">
Loading and status indicators
Apply styles based on state.
<div [ngClass]="{ loading: isLoading, error: hasError }"></div>
Selected items in a list
Real Codebase Usage
In real Angular projects, developers often choose between [class.className] and [ngClass] based on complexity.
Use [class.className] for one class
This is the cleanest option when you only need to toggle a single class.
<button [class.disabled]="isSaving">Save</button>
Use [ngClass] for multiple classes
<div [ngClass]="{
active: isActive,
disabled: isDisabled,
error: hasError
}"></div>
Common patterns in real code
Guarding visual states
<div [class.hidden]="!user"></div>
Validation styling
< []=>
Common Mistakes
1. Using *ngClass instead of [ngClass]
Broken code:
<li *ngClass="{ active: isActive }">Item</li>
Correct code:
<li [ngClass]="{ active: isActive }">Item</li>
Why it fails:
*is for structural directives.ngClassis an attribute directive.
2. Forgetting quotes around string values
Broken code:
<li [class.active]="step === step1">Step1</li>
Correct code:
<li [class.active]=>Step1
Comparisons
| Approach | Use case | Example | Notes |
|---|---|---|---|
[class.active] | Toggle one class | [class.active]="isActive" | Simple and readable |
[ngClass] with object | Toggle multiple classes | [ngClass]="{ active: isActive, error: hasError }" | Best for several conditions |
[ngClass] with string | Apply fixed or computed class names | [ngClass]="'active highlight'" | Useful when classes come from code |
[ngClass] with array | Combine several class values | [ngClass]="['active', sizeClass]" |
Cheat Sheet
<!-- One conditional class -->
<div [class.active]="isActive"></div>
<!-- Multiple conditional classes -->
<div [ngClass]="{ active: isActive, error: hasError }"></div>
<!-- Class from string -->
<div [ngClass]="currentClass"></div>
<!-- Class from array -->
<div [ngClass]="['btn', sizeClass]"></div>
Rules
- Use
[ngClass], not*ngClass - Use
*only with structural directives like*ngIfand*ngFor - Use
[class.className]for one class - Use
===to compare values in conditions - Quote string literals like
'step1'
FAQ
Why does *ngClass cause an Angular error?
Because * tells Angular to treat the directive as structural, but ngClass is not structural. It should be bound with [ngClass].
Should I use [ngClass] or [class.active]?
Use [class.active] when toggling one class. Use [ngClass] when applying multiple classes or building classes dynamically.
Is ngClass the same as class?
No. class applies fixed classes, while ngClass lets Angular add or remove classes based on component data.
Can I use a function inside ngClass?
Yes, but keep template logic simple. If the function is expensive or unclear, compute the value in the component instead.
What is the difference between *ngIf and [ngClass]?
*ngIf adds or removes an element from the DOM. keeps the element and only changes its CSS classes.
Mini Project
Description
Build a simple Angular step navigation component that highlights the currently selected step. This project demonstrates conditional class binding, click event handling, and state-driven UI updates.
Goal
Create a three-step navigation where clicking a step updates the active class correctly.
Requirements
- Create a component with a
stepproperty - Render three clickable steps in the template
- Apply an
activeclass only to the selected step - Change the selected step when the user clicks an item
- Add CSS so the active step looks visually different
Keep learning
Related questions
CSS :not() Selector for Elements Without a Class or Attribute
Learn how to use the CSS :not() selector to target elements that do not have a specific class or attribute, with examples and common pitfalls.
CSS Font Scaling Relative to Container Size: %, em, rem, vw, and Responsive Text
Learn how CSS font scaling really works and how to make text responsive using %, em, rem, vw, clamp(), and media queries.
CSS Parent Selector Explained: Selecting a Parent <li> from an <a>
Learn whether CSS has a parent selector, how :has() works, and practical alternatives for styling a parent li from a child anchor.