From 92afad6ebcb7d375bfffdd9c72017d6438351035 Mon Sep 17 00:00:00 2001 From: Pawel Kozlowski Date: Thu, 12 Feb 2015 21:34:20 +0100 Subject: [PATCH] feat: support bindings for the 'role' attribute Closes #630 --- .../pipeline/element_binder_builder.js | 16 +++++++- .../pipeline/element_binder_builder_spec.js | 41 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) 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 5b9094587f..593d65a675 100644 --- a/modules/angular2/src/core/compiler/pipeline/element_binder_builder.js +++ b/modules/angular2/src/core/compiler/pipeline/element_binder_builder.js @@ -1,4 +1,4 @@ -import {int, isPresent, isBlank, Type, BaseException, StringWrapper, RegExpWrapper, stringify} from 'angular2/src/facade/lang'; +import {int, isPresent, isBlank, Type, BaseException, StringWrapper, RegExpWrapper, isString, stringify} from 'angular2/src/facade/lang'; import {Element, DOM} from 'angular2/src/facade/dom'; import {ListWrapper, List, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection'; @@ -81,6 +81,18 @@ function styleSetterFactory(styleName:string, stylesuffix:string) { return setterFn; } +const ROLE_ATTR = 'role'; +function roleSetter(element:Element, value) { + if (isString(value)) { + DOM.setAttribute(element, ROLE_ATTR, value); + } else { + DOM.removeAttribute(element, ROLE_ATTR); + if (isPresent(value)) { + throw new BaseException("Invalid role attribute, only string values are allowed, got '" + stringify(value) + "'"); + } + } +} + /** * Creates the ElementBinders and adds watches to the * ProtoChangeDetector. @@ -155,6 +167,8 @@ export class ElementBinderBuilder extends CompileStep { if (StringWrapper.startsWith(property, ARIA_PREFIX)) { setterFn = ariaSetterFactory(property); + } else if (StringWrapper.equals(property, ROLE_ATTR)) { + setterFn = roleSetter; } else if (StringWrapper.startsWith(property, CLASS_PREFIX)) { setterFn = classSetterFactory(StringWrapper.substring(property, CLASS_PREFIX.length)); } else if (StringWrapper.startsWith(property, STYLE_PREFIX)) { diff --git a/modules/angular2/test/core/compiler/pipeline/element_binder_builder_spec.js b/modules/angular2/test/core/compiler/pipeline/element_binder_builder_spec.js index 9846c76620..18a724e687 100644 --- a/modules/angular2/test/core/compiler/pipeline/element_binder_builder_spec.js +++ b/modules/angular2/test/core/compiler/pipeline/element_binder_builder_spec.js @@ -241,6 +241,47 @@ export function main() { expect(DOM.getAttribute(view.nodes[0], 'aria-busy')).toEqual('false'); }); + it('should bind to ARIA role attribute', () => { + var propertyBindings = MapWrapper.createFromStringMap({ + 'role': '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 = 'alert'; + changeDetector.detectChanges(); + expect(DOM.getAttribute(view.nodes[0], 'role')).toEqual('alert'); + + evalContext.prop1 = 'alertdialog'; + changeDetector.detectChanges(); + expect(DOM.getAttribute(view.nodes[0], 'role')).toEqual('alertdialog'); + + evalContext.prop1 = null; + changeDetector.detectChanges(); + expect(DOM.getAttribute(view.nodes[0], 'role')).toBeNull(); + }); + + it('should throw for a non-string ARIA role', () => { + var propertyBindings = MapWrapper.createFromStringMap({ + 'role': 'prop1' + }); + var pipeline = createPipeline({propertyBindings: propertyBindings}); + var results = pipeline.process(el('
')); + var pv = results[0].inheritedProtoView; + + instantiateView(pv); + + expect( () => { + evalContext.prop1 = 1; //invalid, non-string role + changeDetector.detectChanges(); + }).toThrowError("Invalid role attribute, only string values are allowed, got '1'"); + }); + it('should bind class with a dot', () => { var propertyBindings = MapWrapper.createFromStringMap({ 'class.bar': 'prop1',