parent
ab9438ffdf
commit
7ce4f66cdc
@ -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 {Element, DOM} from 'facade/src/dom';
|
||||||
import {ListWrapper, List, MapWrapper, StringMapWrapper} from 'facade/src/collection';
|
import {ListWrapper, List, MapWrapper, StringMapWrapper} from 'facade/src/collection';
|
||||||
|
|
||||||
@ -16,6 +16,26 @@ import {CompileStep} from './compile_step';
|
|||||||
import {CompileElement} from './compile_element';
|
import {CompileElement} from './compile_element';
|
||||||
import {CompileControl} from './compile_control';
|
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
|
* Creates the ElementBinders and adds watches to the
|
||||||
* ProtoChangeDetector.
|
* ProtoChangeDetector.
|
||||||
@ -72,8 +92,16 @@ export class ElementBinderBuilder extends CompileStep {
|
|||||||
|
|
||||||
_bindElementProperties(protoView, compileElement) {
|
_bindElementProperties(protoView, compileElement) {
|
||||||
MapWrapper.forEach(compileElement.propertyBindings, (expression, property) => {
|
MapWrapper.forEach(compileElement.propertyBindings, (expression, property) => {
|
||||||
if (DOM.hasProperty(compileElement.element, property)) {
|
var setterFn;
|
||||||
protoView.bindElementProperty(expression.ast, property, reflector.setter(property));
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,22 @@ export function main() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should consume element binding for class attribute', (done) => {
|
||||||
|
compiler.compile(MyComp, el('<div class="foo" [class.bar]="boolProp"></div>')).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) => {
|
it('should support nested components.', (done) => {
|
||||||
compiler.compile(MyComp, el('<child-cmp></child-cmp>')).then((pv) => {
|
compiler.compile(MyComp, el('<child-cmp></child-cmp>')).then((pv) => {
|
||||||
createView(pv);
|
createView(pv);
|
||||||
@ -147,6 +163,7 @@ class MyDir {
|
|||||||
})
|
})
|
||||||
class MyComp {
|
class MyComp {
|
||||||
ctxProp:string;
|
ctxProp:string;
|
||||||
|
boolProp:boolean;
|
||||||
constructor() {
|
constructor() {
|
||||||
this.ctxProp = 'initial value';
|
this.ctxProp = 'initial value';
|
||||||
}
|
}
|
||||||
|
@ -176,6 +176,27 @@ export function main() {
|
|||||||
expect(view.nodes[0].hidden).toEqual(false);
|
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('<input class="foo" viewroot prop-binding>'));
|
||||||
|
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', () => {
|
it('should bind events', () => {
|
||||||
var eventBindings = MapWrapper.createFromStringMap({
|
var eventBindings = MapWrapper.createFromStringMap({
|
||||||
'event1': '1+1'
|
'event1': '1+1'
|
||||||
|
@ -102,6 +102,9 @@ class DOM {
|
|||||||
static void addClass(Element element, String classname) {
|
static void addClass(Element element, String classname) {
|
||||||
element.classes.add(classname);
|
element.classes.add(classname);
|
||||||
}
|
}
|
||||||
|
static void removeClass(Element element, String classname) {
|
||||||
|
element.classes.remove(classname);
|
||||||
|
}
|
||||||
static bool hasClass(Element element, String classname) =>
|
static bool hasClass(Element element, String classname) =>
|
||||||
element.classes.contains(classname);
|
element.classes.contains(classname);
|
||||||
|
|
||||||
|
@ -121,6 +121,9 @@ export class DOM {
|
|||||||
static addClass(element:Element, classname:string) {
|
static addClass(element:Element, classname:string) {
|
||||||
element.classList.add(classname);
|
element.classList.add(classname);
|
||||||
}
|
}
|
||||||
|
static removeClass(element:Element, classname:string) {
|
||||||
|
element.classList.remove(classname);
|
||||||
|
}
|
||||||
static hasClass(element:Element, classname:string) {
|
static hasClass(element:Element, classname:string) {
|
||||||
return element.classList.contains(classname);
|
return element.classList.contains(classname);
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,10 @@ class StringWrapper {
|
|||||||
return s.replaceAll(from, replace);
|
return s.replaceAll(from, replace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static startsWith(String s, String start) {
|
||||||
|
return s.startsWith(start);
|
||||||
|
}
|
||||||
|
|
||||||
static String substring(String s, int start, [int end]) {
|
static String substring(String s, int start, [int end]) {
|
||||||
return s.substring(start, end);
|
return s.substring(start, end);
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,10 @@ export class StringWrapper {
|
|||||||
return s.replace(from.multiple, replace);
|
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) {
|
static substring(s:string, start:int, end:int = undefined) {
|
||||||
return s.substring(start, end);
|
return s.substring(start, end);
|
||||||
}
|
}
|
||||||
@ -219,4 +223,4 @@ export function assertionsEnabled():boolean {
|
|||||||
|
|
||||||
export function print(obj) {
|
export function print(obj) {
|
||||||
console.log(obj);
|
console.log(obj);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user