feat(compiler): allow setting attributes on a host element

Closes #1402
This commit is contained in:
Pawel Kozlowski
2015-05-01 13:41:56 +02:00
parent 7225416661
commit 51839ca677
12 changed files with 107 additions and 1 deletions

View File

@ -598,6 +598,28 @@ export class Directive extends Injectable {
*/
hostProperties:any; // String map
/**
* Specifies static attributes that should be propagated to a host element. Attributes specified in `hostAttributes`
* are propagated only if a given attribute is not present on a host element.
*
* ## Syntax
*
* ```
* @Directive({
* selector: '[my-button]',
* hostAttributes: {
* 'role': 'button'
* }
* })
* class MyButton {
* }
*
* In this example using `my-button` directive (ex.: `<div my-button></div>`) on a host element (here: `<div>` )
* will ensure that this element will get the "button" role.
* ```
*/
hostAttributes:any; // String map
/**
* Specifies a set of lifecycle hostListeners in which the directive participates.
*
@ -618,6 +640,7 @@ export class Directive extends Injectable {
events,
hostListeners,
hostProperties,
hostAttributes,
lifecycle,
compileChildren = true,
}:{
@ -626,6 +649,7 @@ export class Directive extends Injectable {
events:List,
hostListeners: any,
hostProperties: any,
hostAttributes: any,
lifecycle:List,
compileChildren:boolean
}={})
@ -636,6 +660,7 @@ export class Directive extends Injectable {
this.events = events;
this.hostListeners = hostListeners;
this.hostProperties = hostProperties;
this.hostAttributes = hostAttributes;
this.lifecycle = lifecycle;
this.compileChildren = compileChildren;
}
@ -797,6 +822,7 @@ export class Component extends Directive {
events,
hostListeners,
hostProperties,
hostAttributes,
injectables,
lifecycle,
changeDetection = DEFAULT,
@ -807,6 +833,7 @@ export class Component extends Directive {
events:List,
hostListeners:any,
hostProperties:any,
hostAttributes:any,
injectables:List,
lifecycle:List,
changeDetection:string,
@ -819,6 +846,7 @@ export class Component extends Directive {
events: events,
hostListeners: hostListeners,
hostProperties: hostProperties,
hostAttributes: hostAttributes,
lifecycle: lifecycle,
compileChildren: compileChildren
});

View File

@ -247,6 +247,7 @@ export class Compiler {
compileChildren: compileChildren,
hostListeners: isPresent(ann.hostListeners) ? MapWrapper.createFromStringMap(ann.hostListeners) : null,
hostProperties: isPresent(ann.hostProperties) ? MapWrapper.createFromStringMap(ann.hostProperties) : null,
hostAttributes: isPresent(ann.hostAttributes) ? MapWrapper.createFromStringMap(ann.hostAttributes) : null,
properties: isPresent(ann.properties) ? MapWrapper.createFromStringMap(ann.properties) : null,
readAttributes: readAttributes
});

View File

@ -248,6 +248,9 @@ class BrowserDomAdapter extends GenericBrowserDomAdapter {
return new Map.from(element.attributes);
}
bool hasAttribute(Element element, String attribute) =>
element.attributes.containsKey(attribute);
String getAttribute(Element element, String attribute) =>
element.getAttribute(attribute);

View File

@ -263,6 +263,9 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter {
}
return res;
}
hasAttribute(element, attribute:string) {
return element.hasAttribute(attribute);
}
getAttribute(element, attribute:string) {
return element.getAttribute(attribute);
}

View File

@ -199,6 +199,9 @@ export class DomAdapter {
attributeMap(element) {
throw _abstract();
}
hasAttribute(element, attribute:string):boolean {
throw _abstract();
}
getAttribute(element, attribute:string):string {
throw _abstract();
}

View File

@ -211,6 +211,9 @@ class Html5LibDomAdapter implements DomAdapter {
});
return map;
}
hasAttribute(element, String attribute) {
throw 'not implemented';
}
getAttribute(element, String attribute) {
throw 'not implemented';
}

View File

@ -384,6 +384,9 @@ export class Parse5DomAdapter extends DomAdapter {
}
return res;
}
hasAttribute(element, attribute:string) {
return element.attribs && element.attribs.hasOwnProperty(attribute);
}
getAttribute(element, attribute:string) {
return element.attribs && element.attribs.hasOwnProperty(attribute)? element.attribs[attribute]: null;
}

View File

@ -116,15 +116,17 @@ export class DirectiveMetadata {
compileChildren:boolean;
hostListeners:Map<string, string>;
hostProperties:Map<string, string>;
hostAttributes:Map<string, string>;
properties:Map<string, string>;
readAttributes:List<string>;
type:number;
constructor({id, selector, compileChildren, hostListeners, hostProperties, properties, readAttributes, type}) {
constructor({id, selector, compileChildren, hostListeners, hostProperties, hostAttributes, properties, readAttributes, type}) {
this.id = id;
this.selector = selector;
this.compileChildren = isPresent(compileChildren) ? compileChildren : true;
this.hostListeners = hostListeners;
this.hostProperties = hostProperties;
this.hostAttributes = hostAttributes;
this.properties = properties;
this.readAttributes = readAttributes;
this.type = type;

View File

@ -78,6 +78,13 @@ export class DirectiveParser extends CompileStep {
this._bindHostProperty(hostPropertyName, directivePropertyName, current, directiveBinderBuilder);
});
}
if (isPresent(directive.hostAttributes)) {
MapWrapper.forEach(directive.hostAttributes, (hostAttrValue, hostAttrName) => {
if (!DOM.hasAttribute(current.element, hostAttrName)) {
DOM.setAttribute(current.element, hostAttrName, hostAttrValue);
}
});
}
if (isPresent(directive.readAttributes)) {
ListWrapper.forEach(directive.readAttributes, (attrName) => {
elementBinder.readAttribute(attrName);

View File

@ -13,6 +13,7 @@ export function directiveMetadataToMap(meta: DirectiveMetadata): Map {
['compileChildren', meta.compileChildren],
['hostListeners', _cloneIfPresent(meta.hostListeners)],
['hostProperties', _cloneIfPresent(meta.hostProperties)],
['hostAttributes', _cloneIfPresent(meta.hostAttributes)],
['properties', _cloneIfPresent(meta.properties)],
['readAttributes', _cloneIfPresent(meta.readAttributes)],
['type', meta.type],
@ -32,6 +33,7 @@ export function directiveMetadataFromMap(map: Map): DirectiveMetadata {
compileChildren: MapWrapper.get(map, 'compileChildren'),
hostListeners: _cloneIfPresent(MapWrapper.get(map, 'hostListeners')),
hostProperties: _cloneIfPresent(MapWrapper.get(map, 'hostProperties')),
hostAttributes: _cloneIfPresent(MapWrapper.get(map, 'hostAttributes')),
properties: _cloneIfPresent(MapWrapper.get(map, 'properties')),
readAttributes: _cloneIfPresent(MapWrapper.get(map, 'readAttributes')),
type: MapWrapper.get(map, 'type')