ng-class in Angular2

Marko Gresak picture Marko Gresak · May 17, 2015 · Viewed 82.1k times · Source

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.

Answer

Mark Rajcok picture Mark Rajcok · Nov 14, 2015

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;
}

Plunker

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.