Skip to content

Commit 92afad6

Browse files
feat: support bindings for the 'role' attribute
Closes angular#630
1 parent 1846ce8 commit 92afad6

2 files changed

Lines changed: 56 additions & 1 deletion

File tree

‎modules/angular2/src/core/compiler/pipeline/element_binder_builder.js‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {int, isPresent, isBlank, Type, BaseException, StringWrapper, RegExpWrapper, stringify} from 'angular2/src/facade/lang';
1+
import {int, isPresent, isBlank, Type, BaseException, StringWrapper, RegExpWrapper, isString, stringify} from 'angular2/src/facade/lang';
22
import {Element, DOM} from 'angular2/src/facade/dom';
33
import {ListWrapper, List, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
44

@@ -81,6 +81,18 @@ function styleSetterFactory(styleName:string, stylesuffix:string) {
8181
return setterFn;
8282
}
8383

84+
const ROLE_ATTR = 'role';
85+
function roleSetter(element:Element, value) {
86+
if (isString(value)) {
87+
DOM.setAttribute(element, ROLE_ATTR, value);
88+
} else {
89+
DOM.removeAttribute(element, ROLE_ATTR);
90+
if (isPresent(value)) {
91+
throw new BaseException("Invalid role attribute, only string values are allowed, got '" + stringify(value) + "'");
92+
}
93+
}
94+
}
95+
8496
/**
8597
* Creates the ElementBinders and adds watches to the
8698
* ProtoChangeDetector.
@@ -155,6 +167,8 @@ export class ElementBinderBuilder extends CompileStep {
155167

156168
if (StringWrapper.startsWith(property, ARIA_PREFIX)) {
157169
setterFn = ariaSetterFactory(property);
170+
} else if (StringWrapper.equals(property, ROLE_ATTR)) {
171+
setterFn = roleSetter;
158172
} else if (StringWrapper.startsWith(property, CLASS_PREFIX)) {
159173
setterFn = classSetterFactory(StringWrapper.substring(property, CLASS_PREFIX.length));
160174
} else if (StringWrapper.startsWith(property, STYLE_PREFIX)) {

‎modules/angular2/test/core/compiler/pipeline/element_binder_builder_spec.js‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,47 @@ export function main() {
241241
expect(DOM.getAttribute(view.nodes[0], 'aria-busy')).toEqual('false');
242242
});
243243

244+
it('should bind to ARIA role attribute', () => {
245+
var propertyBindings = MapWrapper.createFromStringMap({
246+
'role': 'prop1'
247+
});
248+
var pipeline = createPipeline({propertyBindings: propertyBindings});
249+
var results = pipeline.process(el('<div viewroot prop-binding></div>'));
250+
var pv = results[0].inheritedProtoView;
251+
252+
expect(pv.elementBinders[0].hasElementPropertyBindings).toBe(true);
253+
254+
instantiateView(pv);
255+
256+
evalContext.prop1 = 'alert';
257+
changeDetector.detectChanges();
258+
expect(DOM.getAttribute(view.nodes[0], 'role')).toEqual('alert');
259+
260+
evalContext.prop1 = 'alertdialog';
261+
changeDetector.detectChanges();
262+
expect(DOM.getAttribute(view.nodes[0], 'role')).toEqual('alertdialog');
263+
264+
evalContext.prop1 = null;
265+
changeDetector.detectChanges();
266+
expect(DOM.getAttribute(view.nodes[0], 'role')).toBeNull();
267+
});
268+
269+
it('should throw for a non-string ARIA role', () => {
270+
var propertyBindings = MapWrapper.createFromStringMap({
271+
'role': 'prop1'
272+
});
273+
var pipeline = createPipeline({propertyBindings: propertyBindings});
274+
var results = pipeline.process(el('<div viewroot prop-binding></div>'));
275+
var pv = results[0].inheritedProtoView;
276+
277+
instantiateView(pv);
278+
279+
expect( () => {
280+
evalContext.prop1 = 1; //invalid, non-string role
281+
changeDetector.detectChanges();
282+
}).toThrowError("Invalid role attribute, only string values are allowed, got '1'");
283+
});
284+
244285
it('should bind class with a dot', () => {
245286
var propertyBindings = MapWrapper.createFromStringMap({
246287
'class.bar': 'prop1',

0 commit comments

Comments
 (0)