Reputation: 35733
What is wrong with my Angular code? I am getting the following error:
Cannot read property 'remove' of undefined at BrowserDomAdapter.removeClass
<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>
Upvotes: 1239
Views: 2275674
Reputation: 29009
Angular version 2+ provides several ways to add classes conditionally:
Type one
[class.my_class] = "step === 'step1'"
Type two
[ngClass]="{'my_class': step === 'step1'}"
and multiple options:
[ngClass]="{'my_class': step === 'step1', 'my_class2' : step === 'step2' }"
Type three
[ngClass]="{1 : 'my_class1', 2 : 'my_class2', 3 : 'my_class4'}[step]"
Type four
[ngClass]="step == 'step1' ? 'my_class1' : 'my_class2'"
You can find these examples on the the documentation page.
Upvotes: 2796
Reputation: 1332
Some usefull helper pipes for ngClass
@Pipe({
name: 'condition'
})
export class ONgConditionPipe implements PipeTransform {
transform(value: any, condition?: any): any {
if (condition != null) {
return value;
}
if (value) {
return value;
}
}
}
@Pipe({
name: 'default'
})
export class ONgDefaultPipe implements PipeTransform {
transform(value: any, defaultValue?: any): any {
return value ?? defaultValue;
}
}
Example
[ngClass]="[headerClass | default: '', 'cursor-move' | condition: draggable, ('cursor-move2' | condition: draggable) | default: '']"
Upvotes: 0
Reputation: 314
Additionally, you can assign a value returned by a function:
In HTML
<div [ngClass]="setClasses()">...</div>
In component.ts
// Set Dynamic Classes
setClasses() {
let classes = {
constantClass: true,
'conditional-class': this.item.id === 1
}
return classes;
}
Upvotes: 18
Reputation: 1037
The example is a bit big, but triggering a class instead of typing inline is my first preferred approach. This way, you can add as many possibilities as you want to your element. There may be a way for those who want to bind more than one [ngClass] to a single element.
<span class="inline-flex items-center font-medium" [ngClass]="addClass">{{ badge.text }}</span>
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
type Badge = {
size?: 'basic' | 'large';
shape?: 'basic' | 'rounded';
color?: 'gray' | 'red' | 'yellow' | 'green' | 'blue' | 'indigo' | 'purple' | 'pink';
dot?: boolean;
removeButton?: false;
text?: string;
}
@Component({
selector: 'bio-badge',
templateUrl: './badge.component.html',
styleUrls: ['./badge.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class BioBadgeComponent {
@Input() badge!: Badge;
get addClass() {
return {
'px-2.5 py-0.5 text-sx': this.badge.size === 'basic',
'px-3 py-0.5 text-sm': this.badge.size === 'large',
'rounded-full': this.badge.shape === 'basic',
'rounded': this.badge.shape === 'rounded',
'bg-gray-100 text-gray-800': this.badge.color === 'gray',
'bg-red-100 text-red-800': this.badge.color === 'red',
'bg-yellow-100 text-yellow-800': this.badge.color === 'yellow',
'bg-green-100 text-green-800': this.badge.color === 'green',
'bg-blue-100 text-blue-800': this.badge.color === 'blue',
'bg-indigo-100 text-indigo-800': this.badge.color === 'indigo',
'bg-purple-100 text-purple-800': this.badge.color === 'purple',
'bg-pink-100 text-pink-800': this.badge.color === 'pink',
}
}
}
Upvotes: 2
Reputation: 502
If a user wants to display the class on basis of &&
and ||
, then the below one is working for me:
[ngClass]="{'clasname_1': condition_1 && condition_2, 'classname_2': condition_1 && condition2, 'classname_3': condition}"
Example:
[ngClass]="{'approval-panel-mat-drawer-side-left': similar_toil_mode==='side' && showsTheSimilarToilsWithCloseIcon, 'approval-panel-mat-drawer-side-right': similar_toil_mode==='side' && !showsTheSimilarToilsWithCloseIcon, 'approval-panel-mat-drawer-over': similar_toil_mode==='over'}"
Upvotes: 0
Reputation: 69
Try it like this...
Define your class with '':
<ol class="breadcrumb">
<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>
Upvotes: 1
Reputation: 413
ngClass
syntax:
[ngClass]="{'classname' : conditionFlag}"
You can use it like this:
<ol class="breadcrumb">
<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>
Upvotes: 4
Reputation: 3502
In Angular 7.X
The CSS classes are updated as follows, depending on the type of the expression evaluation:
string - the CSS classes listed in the string (space delimited) are added
Array - the CSS classes declared as Array elements are added
Object - keys are CSS classes that get added when the expression given in the value evaluates to a truthy value. Otherwise, they are removed.
<some-element [ngClass]="'first second'">...</some-element>
<some-element [ngClass]="['first', 'second']">...</some-element>
<some-element [ngClass]="{'first': true, 'second': true, 'third': false}">...</some-element>
<some-element [ngClass]="stringExp|arrayExp|objExp">...</some-element>
<some-element [ngClass]="{'class1 class2 class3' : true}">...</some-element>
Upvotes: 19
Reputation: 1077
With the following examples, you can use 'IF ELSE':
<p class="{{condition ? 'checkedClass' : 'uncheckedClass'}}">
<p [ngClass]="condition ? 'checkedClass' : 'uncheckedClass'">
<p [ngClass]="[condition ? 'checkedClass' : 'uncheckedClass']">
Upvotes: 86
Reputation: 867
For an elseif
statement (less comparison), use it like this (for example, you compare three statements):
<div [ngClass]="step === 'step1' ? 'class1' : (step === 'step2' ? 'class2' : 'class3')"> {{step}} </div>
Upvotes: 3
Reputation: 1476
We can make a class dynamic by using the following syntax. In Angular 2 plus, you can do this in various ways:
[ngClass]="{'active': arrayData.length && arrayData[0]?.booleanProperty}"
[ngClass]="{'active': step}"
[ngClass]="step== 'step1'?'active':''"
[ngClass]="step? 'active' : ''"
Upvotes: 8
Reputation: 9
Use:
<div class="collapse in " [ngClass]="(active_tab=='assignservice' || active_tab=='manage')?'show':''" id="collapseExampleOrganization" aria-expanded="true" style="">
<ul>
<li class="nav-item" [ngClass]="{'active': active_tab=='manage'}">
<a routerLink="/main/organization/manage" (click)="activemenu('manage')"> <i class="la la-building-o"></i>
<p>Manage</p></a></li>
<li class="nav-item" [ngClass]="{'active': active_tab=='assignservice'}"><a routerLink="/main/organization/assignservice" (click)="activemenu('assignservice')"><i class="la la-user"></i><p>Add organization</p></a></li>
</ul>
</div>
The code is a good example of an ngClass if-else condition.
[ngClass]="(active_tab=='assignservice' || active_tab=='manage')?'show':''"
[ngClass]="{'active': active_tab=='assignservice'}"
Upvotes: 1
Reputation: 1525
It is not relevant with the [ngClass]
directive, but I was also getting the same error as
Cannot read property 'remove' of undefined at...
and I thought it to be the error in my [ngClass]
condition, but it turned out the property I was trying to access in the condition of [ngClass]
was not initialized.
Like I had this in my TypeScript file
element: {type: string};
and in my [ngClass]
, I was using
[ngClass]="{'active', element.type === 'active'}"
And I was getting the error
Cannot read property 'type' of undefined at...
and the solution was to fix my property to
element: {type: string} = {type: 'active'};
I hope it helps somebody who is trying to match a condition of a property in [ngClass]
.
Upvotes: 2
Reputation: 5492
Let YourCondition be your condition or a Boolean property. Then do it like this:
[class.yourClass]="YourCondition"
Upvotes: 9
Reputation: 489
To extend MostafaMashayekhi's answer for option two>, you can also chain multiple options with a ','
[ngClass]="{'my-class': step=='step1', 'my-class2':step=='step2' }"
Also *ngIf can be used in some of these situations usually combined with a *ngFor
class="mats p" *ngIf="mat=='painted'"
Upvotes: 10
Reputation: 104870
That's the normal structure. For ngClass
, it is:
[ngClass]="{'classname' : condition}"
So in your case, just use it like this...
<ol class="breadcrumb">
<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>
Upvotes: 96
Reputation: 657937
[ngClass]=...
instead of *ngClass
.
*
is only for the shorthand syntax for structural directives where you can for example use
<div *ngFor="let item of items">{{item}}</div>
instead of the longer equivalent version
<template ngFor let-item [ngForOf]="items">
<div>{{item}}</div>
</template>
See also NgClass.
<some-element [ngClass]="'first second'">...</some-element> <some-element [ngClass]="['first', 'second']">...</some-element> <some-element [ngClass]="{'first': true, 'second': true, 'third': false}">...</some-element> <some-element [ngClass]="stringExp|arrayExp|objExp">...</some-element> <some-element [ngClass]="{'class1 class2 class3' : true}">...</some-element>
See also Template syntax
<!-- Toggle the "special" class on/off with a property --> <div [class.special]="isSpecial">The class binding is special</div> <!-- Binding to `class.special` trumps the class attribute --> <div class="special" [class.special]="!isSpecial">This one is not so special</div>
<!-- Reset/override all class names with a binding --> <div class="bad curly special" [class]="badCurly">Bad curly</div>
Upvotes: 523
Reputation: 8047
Another solution would be using [class.active]
.
Example:
<ol class="breadcrumb">
<li [class.active]="step=='step1'" (click)="step='step1'">Step1</li>
</ol>
Upvotes: 102
Reputation: 202286
You should use something ([ngClass]
instead of *ngClass
) like that:
<ol class="breadcrumb">
<li [ngClass]="{active: step==='step1'}" (click)="step='step1; '">Step1</li>
(...)
</ol>
Upvotes: 21
Reputation: 2017
Angular provides multiple ways to add classes conditionally:
First way
active is your class name
[class.active]="step === 'step1'"
Second way
active is your class name
[ngClass]="{'active': step=='step1'}"
Third way
by using ternary operator class1 and class2 is your class name
[ngClass]="(step=='step1')?'class1':'class2'"
Upvotes: 51
Reputation: 6196
The directive operates in three different ways, depending on which of three types the expression evaluates to:
[class.class_one] = "step === 'step1'"
[ngClass]="{'class_one': step === 'step1'}"
For multiple options:
[ngClass]="{'class_one': step === 'step1', 'class_two' : step === 'step2' }"
[ngClass]="{1 : 'class_one', 2 : 'class_two', 3 : 'class_three'}[step]"
[ngClass]="step == 'step1' ? 'class_one' : 'class_two'"
Upvotes: 5
Reputation: 1716
You can use [ngClass] or [class.classname], both will work the same.
[class.my-class]="step==='step1'"
OR
[ngClass]="{'my-class': step=='step1'}"
Both will work the same!
Upvotes: 9
Reputation: 476
This is what worked for me:
[ngClass]="{'active': dashboardComponent.selected_menu == 'profile'}"
Upvotes: 4
Reputation: 7941
You can use ngClass to apply the class name both conditionally and not in Angular
For Example
[ngClass]="'someClass'">
Conditional
[ngClass]="{'someClass': property1.isValid}">
Multiple Condition
[ngClass]="{'someClass': property1.isValid && property2.isValid}">
Method expression
[ngClass]="getSomeClass()"
This method will inside of your component
getSomeClass(){
const isValid=this.property1 && this.property2;
return {someClass1:isValid , someClass2:isValid};
}
Upvotes: 56
Reputation: 13110
While I was creating a reactive form, I had to assign 2 types of class on the button. This is how I did it:
<button type="submit" class="btn" [ngClass]="(formGroup.valid)?'btn-info':''"
[disabled]="!formGroup.valid">Sign in</button>
When the form is valid, button has btn and btn-class (from bootstrap), otherwise just btn class.
Upvotes: 8