diff --git a/modules/core/src/compiler/pipeline/element_binder_builder.js b/modules/core/src/compiler/pipeline/element_binder_builder.js
index 094d0d1453..f48b50868e 100644
--- a/modules/core/src/compiler/pipeline/element_binder_builder.js
+++ b/modules/core/src/compiler/pipeline/element_binder_builder.js
@@ -1,4 +1,4 @@
-import {int, isPresent, isBlank, Type, BaseException, stringify} from 'facade/src/lang';
+import {int, isPresent, isBlank, Type, BaseException, StringWrapper, stringify} from 'facade/src/lang';
import {Element, DOM} from 'facade/src/dom';
import {ListWrapper, List, MapWrapper, StringMapWrapper} from 'facade/src/collection';
@@ -16,6 +16,26 @@ import {CompileStep} from './compile_step';
import {CompileElement} from './compile_element';
import {CompileControl} from './compile_control';
+const CLASS_PREFIX = 'class.';
+var classSettersCache = StringMapWrapper.create();
+
+function classSetterFactory(className:string) {
+ var setterFn = StringMapWrapper.get(classSettersCache, className);
+
+ if (isBlank(setterFn)) {
+ setterFn = function(element:Element, value) {
+ if (value) {
+ DOM.addClass(element, className);
+ } else {
+ DOM.removeClass(element, className);
+ }
+ };
+ StringMapWrapper.set(classSettersCache, className, setterFn);
+ }
+
+ return setterFn;
+}
+
/**
* Creates the ElementBinders and adds watches to the
* ProtoChangeDetector.
@@ -72,8 +92,16 @@ export class ElementBinderBuilder extends CompileStep {
_bindElementProperties(protoView, compileElement) {
MapWrapper.forEach(compileElement.propertyBindings, (expression, property) => {
- if (DOM.hasProperty(compileElement.element, property)) {
- protoView.bindElementProperty(expression.ast, property, reflector.setter(property));
+ var setterFn;
+
+ if (StringWrapper.startsWith(property, CLASS_PREFIX)) {
+ setterFn = classSetterFactory(StringWrapper.substring(property, CLASS_PREFIX.length));
+ } else if (DOM.hasProperty(compileElement.element, property)) {
+ setterFn = reflector.setter(property);
+ }
+
+ if (isPresent(setterFn)) {
+ protoView.bindElementProperty(expression.ast, property, setterFn);
}
});
}
diff --git a/modules/core/test/compiler/integration_spec.js b/modules/core/test/compiler/integration_spec.js
index c191b7a57c..f2fc902c3c 100644
--- a/modules/core/test/compiler/integration_spec.js
+++ b/modules/core/test/compiler/integration_spec.js
@@ -69,6 +69,22 @@ export function main() {
});
});
+ it('should consume element binding for class attribute', (done) => {
+ compiler.compile(MyComp, el('
')).then((pv) => {
+ createView(pv);
+
+ ctx.boolProp = true;
+ cd.detectChanges();
+ expect(view.nodes[0].className).toEqual('foo ng-binding bar');
+
+ ctx.boolProp = false;
+ cd.detectChanges();
+ expect(view.nodes[0].className).toEqual('foo ng-binding');
+
+ done();
+ });
+ });
+
it('should support nested components.', (done) => {
compiler.compile(MyComp, el('')).then((pv) => {
createView(pv);
@@ -147,6 +163,7 @@ class MyDir {
})
class MyComp {
ctxProp:string;
+ boolProp:boolean;
constructor() {
this.ctxProp = 'initial value';
}
diff --git a/modules/core/test/compiler/pipeline/element_binder_builder_spec.js b/modules/core/test/compiler/pipeline/element_binder_builder_spec.js
index 1cc6b5605a..3cea16d18c 100644
--- a/modules/core/test/compiler/pipeline/element_binder_builder_spec.js
+++ b/modules/core/test/compiler/pipeline/element_binder_builder_spec.js
@@ -176,6 +176,27 @@ export function main() {
expect(view.nodes[0].hidden).toEqual(false);
});
+ it('should bind class with a dot', () => {
+ var propertyBindings = MapWrapper.createFromStringMap({
+ 'class.bar': 'prop1',
+ });
+ var pipeline = createPipeline({propertyBindings: propertyBindings});
+ var results = pipeline.process(el(''));
+ var pv = results[0].inheritedProtoView;
+
+ expect(pv.elementBinders[0].hasElementPropertyBindings).toBe(true);
+
+ instantiateView(pv);
+
+ evalContext.prop1 = true;
+ changeDetector.detectChanges();
+ expect(view.nodes[0].className).toEqual('foo ng-binding bar');
+
+ evalContext.prop1 = false;
+ changeDetector.detectChanges();
+ expect(view.nodes[0].className).toEqual('foo ng-binding');
+ });
+
it('should bind events', () => {
var eventBindings = MapWrapper.createFromStringMap({
'event1': '1+1'
diff --git a/modules/facade/src/dom.dart b/modules/facade/src/dom.dart
index b8607afa6f..2eefdcbc76 100644
--- a/modules/facade/src/dom.dart
+++ b/modules/facade/src/dom.dart
@@ -102,6 +102,9 @@ class DOM {
static void addClass(Element element, String classname) {
element.classes.add(classname);
}
+ static void removeClass(Element element, String classname) {
+ element.classes.remove(classname);
+ }
static bool hasClass(Element element, String classname) =>
element.classes.contains(classname);
diff --git a/modules/facade/src/dom.es6 b/modules/facade/src/dom.es6
index 134dc2ff1c..64bc98af9e 100644
--- a/modules/facade/src/dom.es6
+++ b/modules/facade/src/dom.es6
@@ -121,6 +121,9 @@ export class DOM {
static addClass(element:Element, classname:string) {
element.classList.add(classname);
}
+ static removeClass(element:Element, classname:string) {
+ element.classList.remove(classname);
+ }
static hasClass(element:Element, classname:string) {
return element.classList.contains(classname);
}
diff --git a/modules/facade/src/lang.dart b/modules/facade/src/lang.dart
index 67dd5ff8d3..24cf5cac1e 100644
--- a/modules/facade/src/lang.dart
+++ b/modules/facade/src/lang.dart
@@ -62,6 +62,10 @@ class StringWrapper {
return s.replaceAll(from, replace);
}
+ static startsWith(String s, String start) {
+ return s.startsWith(start);
+ }
+
static String substring(String s, int start, [int end]) {
return s.substring(start, end);
}
diff --git a/modules/facade/src/lang.es6 b/modules/facade/src/lang.es6
index ea12b81891..108efbcda6 100644
--- a/modules/facade/src/lang.es6
+++ b/modules/facade/src/lang.es6
@@ -68,6 +68,10 @@ export class StringWrapper {
return s.replace(from.multiple, replace);
}
+ static startsWith(s:string, start:string) {
+ return s.startsWith(start);
+ }
+
static substring(s:string, start:int, end:int = undefined) {
return s.substring(start, end);
}
@@ -219,4 +223,4 @@ export function assertionsEnabled():boolean {
export function print(obj) {
console.log(obj);
-}
\ No newline at end of file
+}