fix(ng_class): support sets correctly

Previously, NgClass threw in Dart checked mode.

Closes #4910
This commit is contained in:
Tobias Bosch 2015-10-26 09:50:51 -07:00
parent 28db864690
commit 2957b0b32e
2 changed files with 33 additions and 4 deletions

View File

@ -1,4 +1,4 @@
import {isPresent, isString, StringWrapper, isBlank} from 'angular2/src/core/facade/lang'; import {isPresent, isString, StringWrapper, isBlank, isArray} from 'angular2/src/core/facade/lang';
import {DoCheck, OnDestroy} from 'angular2/lifecycle_hooks'; import {DoCheck, OnDestroy} from 'angular2/lifecycle_hooks';
import {Directive} from 'angular2/src/core/metadata'; import {Directive} from 'angular2/src/core/metadata';
import {ElementRef} from 'angular2/src/core/linker'; import {ElementRef} from 'angular2/src/core/linker';
@ -146,10 +146,13 @@ export class NgClass implements DoCheck, OnDestroy {
this._initialClasses.forEach(className => this._toggleClass(className, !isCleanup)); this._initialClasses.forEach(className => this._toggleClass(className, !isCleanup));
} }
private _applyClasses(rawClassVal: string[] | {[key: string]: string}, isCleanup: boolean) { private _applyClasses(rawClassVal: string[] | Set<string>| {[key: string]: string},
isCleanup: boolean) {
if (isPresent(rawClassVal)) { if (isPresent(rawClassVal)) {
if (isListLikeIterable(rawClassVal)) { if (isArray(rawClassVal)) {
(<string[]>rawClassVal).forEach(className => this._toggleClass(className, !isCleanup)); (<string[]>rawClassVal).forEach(className => this._toggleClass(className, !isCleanup));
} else if (rawClassVal instanceof Set) {
(<Set<string>>rawClassVal).forEach(className => this._toggleClass(className, !isCleanup));
} else { } else {
StringMapWrapper.forEach(<{[k: string]: string}>rawClassVal, (expVal, className) => { StringMapWrapper.forEach(<{[k: string]: string}>rawClassVal, (expVal, className) => {
if (expVal) this._toggleClass(className, !isCleanup); if (expVal) this._toggleClass(className, !isCleanup);

View File

@ -14,7 +14,7 @@ import {
it, it,
xit, xit,
} from 'angular2/testing_internal'; } from 'angular2/testing_internal';
import {ListWrapper, StringMapWrapper} from 'angular2/src/core/facade/collection'; import {ListWrapper, StringMapWrapper, SetWrapper} from 'angular2/src/core/facade/collection';
import {Component, View, NgFor, provide} from 'angular2/angular2'; import {Component, View, NgFor, provide} from 'angular2/angular2';
import {NgClass} from 'angular2/src/core/directives/ng_class'; import {NgClass} from 'angular2/src/core/directives/ng_class';
import {APP_VIEW_POOL_CAPACITY} from 'angular2/src/core/linker/view_pool'; import {APP_VIEW_POOL_CAPACITY} from 'angular2/src/core/linker/view_pool';
@ -253,6 +253,29 @@ export function main() {
})); }));
}); });
describe('expressions evaluating to sets', () => {
it('should add and remove classes if the set instance changed',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div [ng-class]="setExpr"></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((rootTC) => {
var setExpr = new Set<string>();
setExpr.add('bar');
rootTC.debugElement.componentInstance.setExpr = setExpr;
detectChangesAndCheck(rootTC, 'bar');
setExpr = new Set<string>();
setExpr.add('baz');
rootTC.debugElement.componentInstance.setExpr = setExpr;
detectChangesAndCheck(rootTC, 'baz');
async.done();
});
}));
});
describe('expressions evaluating to string', () => { describe('expressions evaluating to string', () => {
it('should add classes specified in a string literal', it('should add classes specified in a string literal',
@ -452,6 +475,9 @@ class TestComponent {
condition: boolean = true; condition: boolean = true;
items: any[]; items: any[];
arrExpr: string[] = ['foo']; arrExpr: string[] = ['foo'];
setExpr: Set<string> = new Set<string>();
objExpr = {'foo': true, 'bar': false}; objExpr = {'foo': true, 'bar': false};
strExpr = 'foo'; strExpr = 'foo';
constructor() { this.setExpr.add('foo'); }
} }