Reputation: 8217
I am developing a test application in angular 2 and I'm stuck with a problem of adding classes based on list from model.
In Angular 1 one could do:
// model
$scope.myClasses = ['class1', 'class2', ...];
// view
... ng-class="myClasses" ...
In Angular 2, all I have been able to do so far is:
// view
... [class.class1]="true" [class.class2]="true" ...
Which is obviously not very dynamic and I'm sure there must be a better way to do this.
However, I have also tried:
// model
class ... {
private myClasses: any;
constructor() {
this.myClasses = ['class1', 'class2', ...];
}
// view
... [class]="myClasses" ...
but this doesn't work, I have tried myClasses
as a string name of a single class, array of strings, object with a classname key and true as a value, an array of objects of this kind, but sadly, nothing of listed will work this way.
Upvotes: 34
Views: 83356
Reputation: 24945
One more method [ Using Ternary Operator and Interpolation]
(Altough Mark Rajcok
stated all possible ngClass
methods, but you can couple it with ternary operator
and you get else
condtions)
<div class="hard-coded-class {{classCondition ? 'c1 c2': 'c3 c4'}}">
Conditional classes using <b>Ternary Operator</b>
</div>
or use ternary operator
with ngClass
, see how
export class App {
this.classCondition = false;
}
<div class="hard-coded-class c3 c4">
Conditional classes using <b>Ternary Operator</b>
</div>
Hope it helps someone.
Upvotes: 22
Reputation: 364697
According to the NgClass API docs, Angular 2 will accept a string, an Array, or an Object/map as the expression to NgClass. Or, of course, you could specify a function that returns one of those.
import {Component, CORE_DIRECTIVES} from 'angular2/angular2'
@Component({
selector: 'my-app',
directives: [CORE_DIRECTIVES],
template: `
<div>
<h2>{{title}}</h2>
<div ngClass="gray-border purple">string of classes</div>
<div [ngClass]="'gray-border purple'">string of classes</div>
<div [ngClass]="['gray-border', 'green']">array of classes</div>
<div [ngClass]="{'gray-border': true, 'blue': true}">object/map of classes</div>
<button [ngClass]="{active: isActive}" (click)="isActive = !isActive">Click me</button>
</div>
`,
styles: [`
.gray-border { border: 1px solid gray; }
.blue { color: blue; }
.green { color: green; }
.purple { color: purple; }
.active { background-color: #f55; }
`]
})
export class App {
title = "Angular 2 - NgClass";
isActive = false;
}
If you are passing a literal string, note the two alternative syntaxes:
<div ngClass="gray-border purple">string of classes</div>
<div [ngClass]="'gray-border purple'">string of classes</div>
I believe the first is just syntactic sugar for the second.
And to quote the docs:
While the NgClass directive can interpret expressions evaluating to string, Array or Object, the Object-based version is the most often used and has an advantage of keeping all the CSS class names in a template.
Upvotes: 39
Reputation: 410
I was trying to do something similar, I had a list of menu items and wanted to specify a fontawesome class for each item. This is how I made it work. In my typescript component I had this:
export class AppCmp {
menuItems = [
{
text: 'Editor',
icon: 'fa fa-pencil'
},
{
text: 'Account',
icon: 'fa fa-user'
},
{
text: 'Catalog',
icon: 'fa fa-list'
}
]
}
Then in my html:
<div *ngFor="#item of menuItems; #index = index">
<i [attr.class]="item.icon"></i>
<span>{{ item.text }}</span>
</div>
Here is the plunker, https://plnkr.co/edit/PIDRZsc7ZhISNgZzOWuY?p=preview Hope that helps
Upvotes: 1
Reputation: 746
Using typescript and Angular 2 beta, ngClass doesn't seem to work. From following the API preview - https://angular.io/docs/ts/latest/api/common/NgClass-directive.html
template: '<div [ngClass]="classMap">Class Map</div>'
The example from Google provides two versions of code (which I assume is Alpha and updated to Beta). The new syntax in the website example doesn't seem to work... any ideas?
@View({
template: `
<div class="container questions">
<div class="row formSection">
<h2>
<div [ngClass]="completed">completed</div>
</h2>
<questionSection></questionSection>
</div>
</div>
`,
directives: [NgClass, QuestionSection],
})
Upvotes: 2
Reputation: 48505
You must specify CSSClass
in directives
property of @View
decorator. Check out this plunk.
@Component({
selector: 'app',
})
@View({
template: '<div [class]="classMap">Class Map</div>',
directives: [CSSClass]
})
class App {
constructor() {
this.classMap = { 'class1': true, 'class2': false };
setInterval(() => {
this.classMap.class2 = !this.classMap.class2;
}, 1000)
}
}
UPD
CSSClass
was renamed to NgClass
in alpha-35. See this plunk
@Component({
selector: 'app',
})
@View({
directives: [NgClass],
template: `
<div [ng-class]="classMap">Class Map</div>
`,
})
class App { /* ... */ }
Upvotes: 33