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 4d85a62b16..5b9094587f 100644 --- a/modules/angular2/src/core/compiler/pipeline/element_binder_builder.js +++ b/modules/angular2/src/core/compiler/pipeline/element_binder_builder.js @@ -18,6 +18,26 @@ import {CompileControl} from './compile_control'; var DOT_REGEXP = RegExpWrapper.create('\\.'); +const ARIA_PREFIX = 'aria-'; +var ariaSettersCache = StringMapWrapper.create(); + +function ariaSetterFactory(attrName:string) { + var setterFn = StringMapWrapper.get(ariaSettersCache, attrName); + + if (isBlank(setterFn)) { + setterFn = function(element:Element, value) { + if (isPresent(value)) { + DOM.setAttribute(element, attrName, stringify(value)); + } else { + DOM.removeAttribute(element, attrName); + } + }; + StringMapWrapper.set(ariaSettersCache, attrName, setterFn); + } + + return setterFn; +} + const CLASS_PREFIX = 'class.'; var classSettersCache = StringMapWrapper.create(); @@ -133,7 +153,9 @@ export class ElementBinderBuilder extends CompileStep { MapWrapper.forEach(compileElement.propertyBindings, (expression, property) => { var setterFn, styleParts, styleSuffix; - if (StringWrapper.startsWith(property, CLASS_PREFIX)) { + if (StringWrapper.startsWith(property, ARIA_PREFIX)) { + setterFn = ariaSetterFactory(property); + } else if (StringWrapper.startsWith(property, CLASS_PREFIX)) { setterFn = classSetterFactory(StringWrapper.substring(property, CLASS_PREFIX.length)); } else if (StringWrapper.startsWith(property, STYLE_PREFIX)) { styleParts = StringWrapper.split(property, DOT_REGEXP); diff --git a/modules/angular2/src/facade/dom.dart b/modules/angular2/src/facade/dom.dart index 47f8e3b48c..7822d9518f 100644 --- a/modules/angular2/src/facade/dom.dart +++ b/modules/angular2/src/facade/dom.dart @@ -148,6 +148,12 @@ class DOM { element.setAttribute(name, value); } + static void removeAttribute(Element element, String name) { + //there is no removeAttribute method as of now in Dart: + //https://code.google.com/p/dart/issues/detail?id=19934 + element.attributes.remove(name); + } + static Node templateAwareRoot(Element el) => el is TemplateElement ? el.content : el; diff --git a/modules/angular2/src/facade/dom.es6 b/modules/angular2/src/facade/dom.es6 index 2721928d35..0d38f2e8e2 100644 --- a/modules/angular2/src/facade/dom.es6 +++ b/modules/angular2/src/facade/dom.es6 @@ -166,6 +166,9 @@ export class DOM { static setAttribute(element:Element, name:string, value:string) { element.setAttribute(name, value); } + static removeAttribute(element:Element, attribute:string) { + return element.removeAttribute(attribute); + } static templateAwareRoot(el:Element):Node { return el instanceof TemplateElement ? el.content : el; } diff --git a/modules/angular2/test/core/compiler/integration_spec.js b/modules/angular2/test/core/compiler/integration_spec.js index 66a4311d91..bc29590e36 100644 --- a/modules/angular2/test/core/compiler/integration_spec.js +++ b/modules/angular2/test/core/compiler/integration_spec.js @@ -71,6 +71,24 @@ export function main() { }); }); + it('should consume binding to aria-* attributes', (done) => { + tplResolver.setTemplate(MyComp, new Template({inline: '
'})); + + compiler.compile(MyComp).then((pv) => { + createView(pv); + + ctx.ctxProp = 'Initial aria label'; + cd.detectChanges(); + expect(DOM.getAttribute(view.nodes[0], 'aria-label')).toEqual('Initial aria label'); + + ctx.ctxProp = 'Changed aria label'; + cd.detectChanges(); + expect(DOM.getAttribute(view.nodes[0], 'aria-label')).toEqual('Changed aria label'); + + done(); + }); + }); + it('should consume directive watch expression change.', (done) => { var tpl = '