diff --git a/modules/angular2/src/change_detection/parser/parser.js b/modules/angular2/src/change_detection/parser/parser.js index 16953b00a6..a1e5e804d5 100644 --- a/modules/angular2/src/change_detection/parser/parser.js +++ b/modules/angular2/src/change_detection/parser/parser.js @@ -79,6 +79,10 @@ export class Parser { return new ASTWithSource(new Interpolation(strings, expressions), input, location); } + wrapLiteralPrimitive(input:string, location:any):ASTWithSource { + return new ASTWithSource(new LiteralPrimitive(input), input, location); + } + } class _ParseAST { diff --git a/modules/angular2/src/core/compiler/pipeline/default_steps.js b/modules/angular2/src/core/compiler/pipeline/default_steps.js index 34594e7677..9b6c525f1d 100644 --- a/modules/angular2/src/core/compiler/pipeline/default_steps.js +++ b/modules/angular2/src/core/compiler/pipeline/default_steps.js @@ -35,6 +35,6 @@ export function createDefaultSteps( new ElementBindingMarker(), new ProtoViewBuilder(changeDetection, shadowDomStrategy), new ProtoElementInjectorBuilder(), - new ElementBinderBuilder() + new ElementBinderBuilder(parser, compilationUnit) ]; } diff --git a/modules/angular2/src/core/compiler/pipeline/directive_parser.js b/modules/angular2/src/core/compiler/pipeline/directive_parser.js index b5491c5e47..6d8c79b10c 100644 --- a/modules/angular2/src/core/compiler/pipeline/directive_parser.js +++ b/modules/angular2/src/core/compiler/pipeline/directive_parser.js @@ -1,4 +1,4 @@ -import {isPresent, BaseException} from 'angular2/src/facade/lang'; +import {isPresent, isBlank, BaseException} from 'angular2/src/facade/lang'; import {List, MapWrapper} from 'angular2/src/facade/collection'; import {TemplateElement} from 'angular2/src/facade/dom'; import {SelectorMatcher} from '../selector'; @@ -50,7 +50,10 @@ export class DirectiveParser extends CompileStep { cssSelector.addClassName(classList[i]); } MapWrapper.forEach(attrs, (attrValue, attrName) => { - cssSelector.addAttribute(attrName, attrValue); + if (isBlank(current.propertyBindings) || + isPresent(current.propertyBindings) && !MapWrapper.contains(current.propertyBindings, attrName)) { + cssSelector.addAttribute(attrName, attrValue); + } }); if (isPresent(current.propertyBindings)) { MapWrapper.forEach(current.propertyBindings, (expression, prop) => { diff --git a/modules/angular2/src/core/compiler/pipeline/element_binder_builder.js b/modules/angular2/src/core/compiler/pipeline/element_binder_builder.js index 848242fde9..0e8ed18971 100644 --- a/modules/angular2/src/core/compiler/pipeline/element_binder_builder.js +++ b/modules/angular2/src/core/compiler/pipeline/element_binder_builder.js @@ -86,6 +86,13 @@ function styleSetterFactory(styleName:string, stylesuffix:string) { * with the flag `isViewRoot`. */ export class ElementBinderBuilder extends CompileStep { + _parser:Parser; + _compilationUnit:any; + constructor(parser:Parser, compilationUnit:any) { + this._parser = parser; + this._compilationUnit = compilationUnit; + } + process(parent:CompileElement, current:CompileElement, control:CompileControl) { var elementBinder = null; if (current.hasBindings) { @@ -149,13 +156,19 @@ export class ElementBinderBuilder extends CompileStep { var directive = ListWrapper.get(directives, directiveIndex); var annotation = directive.annotation; if (isBlank(annotation.bind)) continue; + var _this = this; StringMapWrapper.forEach(annotation.bind, function (dirProp, elProp) { var expression = isPresent(compileElement.propertyBindings) ? MapWrapper.get(compileElement.propertyBindings, elProp) : null; if (isBlank(expression)) { - throw new BaseException("No element binding found for property '" + elProp + var attributeValue = MapWrapper.get(compileElement.attrs(), elProp); + if (isPresent(attributeValue)) { + expression = _this._parser.wrapLiteralPrimitive(attributeValue, _this._compilationUnit); + } else { + throw new BaseException("No element binding found for property '" + elProp + "' which is required by directive '" + stringify(directive.type) + "'"); + } } var len = dirProp.length; var dirBindingName = dirProp; diff --git a/modules/angular2/test/change_detection/parser/parser_spec.js b/modules/angular2/test/change_detection/parser/parser_spec.js index 4e702bd84e..3ddbe628cd 100644 --- a/modules/angular2/test/change_detection/parser/parser_spec.js +++ b/modules/angular2/test/change_detection/parser/parser_spec.js @@ -543,6 +543,12 @@ export function main() { expect(ast.expressions[1].name).toEqual('b'); }); }); + + describe('wrapLiteralPrimitive', () => { + it('should wrap a literal primitive', () => { + expect(createParser().wrapLiteralPrimitive("foo", null).eval(null)).toEqual("foo"); + }); + }); }); } diff --git a/modules/angular2/test/core/compiler/integration_spec.js b/modules/angular2/test/core/compiler/integration_spec.js index f6fd816463..9e687e8661 100644 --- a/modules/angular2/test/core/compiler/integration_spec.js +++ b/modules/angular2/test/core/compiler/integration_spec.js @@ -65,14 +65,23 @@ export function main() { }); it('should consume directive watch expression change.', (done) => { - compiler.compile(MyComp, el('
')).then((pv) => { + var tpl = + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + compiler.compile(MyComp, el(tpl)).then((pv) => { createView(pv); ctx.ctxProp = 'Hello World!'; cd.detectChanges(); - var elInj = view.elementInjectors[0]; - expect(elInj.get(MyDir).dirProp).toEqual('Hello World!'); + expect(view.elementInjectors[0].get(MyDir).dirProp).toEqual('Hello World!'); + expect(view.elementInjectors[1].get(MyDir).dirProp).toEqual('Hi there!'); + expect(view.elementInjectors[2].get(MyDir).dirProp).toEqual('Hi there!'); + expect(view.elementInjectors[3].get(MyDir).dirProp).toEqual('One more Hello World!'); done(); }); }); diff --git a/modules/angular2/test/core/compiler/pipeline/directive_parser_spec.js b/modules/angular2/test/core/compiler/pipeline/directive_parser_spec.js index 2a1b6bd6f9..91759f3df1 100644 --- a/modules/angular2/test/core/compiler/pipeline/directive_parser_spec.js +++ b/modules/angular2/test/core/compiler/pipeline/directive_parser_spec.js @@ -24,6 +24,7 @@ export function main() { directives = [ SomeDecorator, SomeDecoratorIgnoringChildren, + SomeDecoratorWithBinding, SomeTemplate, SomeTemplate2, SomeComponent, @@ -182,6 +183,15 @@ export function main() { ); }).toThrowError('Only template directives are allowed on