feat(Directive): Have a single Directive.host which mimics HTML

fixes #2268

BREAKING CHANGE:

Before

    @Directive({
      hostListeners: {'event': 'statement'},
      hostProperties: {'expression': 'hostProp'},
      hostAttributes: {'attr': 'value'},
      hostActions: {'action': 'statement'}
    })

After

    @Directive({
      host: {
        '(event)': 'statement',
        '[hostProp]': 'expression'  // k & v swapped
        'attr': 'value',
        '@action': 'statement'
      }
    })
This commit is contained in:
Victor Berchet 2015-06-09 12:33:40 +02:00 committed by Tobias Bosch
parent 47b6b05017
commit f3b49378e4
32 changed files with 316 additions and 242 deletions

View File

@ -585,6 +585,8 @@ export class Directive extends Injectable {
*/
events: List<string>;
// TODO(vicb): doc
/**
* Specifies which DOM hostListeners a directive listens to.
*
@ -643,9 +645,6 @@ export class Directive extends Injectable {
* 'change' event.
*
*/
hostListeners: StringMap<string, string>;
/**
* Specifies which DOM properties a directives updates.
*
@ -667,8 +666,6 @@ export class Directive extends Injectable {
* the host element.
* ```
*/
hostProperties: StringMap<string, string>;
/**
* Specifies static attributes that should be propagated to a host element. Attributes specified
* in `hostAttributes`
@ -691,8 +688,6 @@ export class Directive extends Injectable {
* will ensure that this element will get the "button" role.
* ```
*/
hostAttributes: StringMap<string, string>;
/**
* Specifies which DOM methods a directive can invoke.
*
@ -719,7 +714,8 @@ export class Directive extends Injectable {
* element.
* ```
*/
hostActions: StringMap<string, string>;
host: StringMap<string, string>;
/**
* Specifies which lifecycle should be notified to the directive.
@ -795,16 +791,13 @@ export class Directive extends Injectable {
exportAs: string;
constructor({
selector, properties, events, hostListeners, hostProperties, hostAttributes,
hostActions, lifecycle, hostInjector, exportAs, compileChildren = true,
selector, properties, events, host, lifecycle, hostInjector, exportAs,
compileChildren = true,
}: {
selector?: string,
properties?: List<string>,
events?: List<string>,
hostListeners?: StringMap<string, string>,
hostProperties?: StringMap<string, string>,
hostAttributes?: StringMap<string, string>,
hostActions?: StringMap<string, string>,
host?: StringMap<string, string>,
lifecycle?: List<LifecycleEvent>,
hostInjector?: List<any>,
exportAs?: string,
@ -814,10 +807,7 @@ export class Directive extends Injectable {
this.selector = selector;
this.properties = properties;
this.events = events;
this.hostListeners = hostListeners;
this.hostProperties = hostProperties;
this.hostAttributes = hostAttributes;
this.hostActions = hostActions;
this.host = host;
this.exportAs = exportAs;
this.lifecycle = lifecycle;
this.compileChildren = compileChildren;
@ -1022,16 +1012,12 @@ export class Component extends Directive {
*/
viewInjector: List<any>;
constructor({selector, properties, events, hostListeners, hostProperties, hostAttributes,
hostActions, exportAs, appInjector, lifecycle, hostInjector, viewInjector,
changeDetection = DEFAULT, compileChildren = true}: {
constructor({selector, properties, events, host, exportAs, appInjector, lifecycle, hostInjector,
viewInjector, changeDetection = DEFAULT, compileChildren = true}: {
selector?: string,
properties?: List<string>,
events?: List<string>,
hostListeners?: StringMap<string, string>,
hostProperties?: StringMap<string, string>,
hostAttributes?: StringMap<string, string>,
hostActions?: StringMap<string, string>,
host?: StringMap<string, string>,
exportAs?: string,
appInjector?: List<any>,
lifecycle?: List<LifecycleEvent>,
@ -1044,10 +1030,7 @@ export class Component extends Directive {
selector: selector,
properties: properties,
events: events,
hostListeners: hostListeners,
hostProperties: hostProperties,
hostAttributes: hostAttributes,
hostActions: hostActions,
host: host,
exportAs: exportAs,
hostInjector: hostInjector,
lifecycle: lifecycle,

View File

@ -293,21 +293,14 @@ export class DirectiveBinding extends ResolvedBinding {
var resolvedViewInjectables = ann instanceof Component && isPresent(ann.viewInjector) ?
resolveBindings(ann.viewInjector) :
[];
var metadata = new DirectiveMetadata({
var metadata = DirectiveMetadata.create({
id: stringify(rb.key.token),
type: ann instanceof
Component ? DirectiveMetadata.COMPONENT_TYPE : DirectiveMetadata.DIRECTIVE_TYPE,
selector: ann.selector,
compileChildren: ann.compileChildren,
events: ann.events,
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,
hostActions: isPresent(ann.hostActions) ? MapWrapper.createFromStringMap(ann.hostActions) :
null,
host: isPresent(ann.host) ? MapWrapper.createFromStringMap(ann.host) : null,
properties: ann.properties,
readAttributes: DirectiveBinding._readAttributes(deps),

View File

@ -16,15 +16,16 @@ import {ControlValueAccessor} from './control_value_accessor';
@Directive({
selector:
'input[type=checkbox][ng-control],input[type=checkbox][ng-form-control],input[type=checkbox][ng-model]',
hostListeners: {'change': 'onChange($event.target.checked)', 'blur': 'onTouched()'},
hostProperties: {
'checked': 'checked',
'cd.control?.untouched == true': 'class.ng-untouched',
'cd.control?.touched == true': 'class.ng-touched',
'cd.control?.pristine == true': 'class.ng-pristine',
'cd.control?.dirty == true': 'class.ng-dirty',
'cd.control?.valid == true': 'class.ng-valid',
'cd.control?.valid == false': 'class.ng-invalid'
host: {
'(change)': 'onChange($event.target.checked)',
'(blur)': 'onTouched()',
'[checked]': 'checked',
'[class.ng-untouched]': 'cd.control?.untouched == true',
'[class.ng-touched]': 'cd.control?.touched == true',
'[class.ng-pristine]': 'cd.control?.pristine == true',
'[class.ng-dirty]': 'cd.control?.dirty == true',
'[class.ng-valid]': 'cd.control?.valid == true',
'[class.ng-invalid]': 'cd.control?.valid == false'
}
})
export class CheckboxControlValueAccessor implements ControlValueAccessor {

View File

@ -19,19 +19,17 @@ import {isBlank} from 'angular2/src/facade/lang';
@Directive({
selector:
'input:not([type=checkbox])[ng-control],textarea[ng-control],input:not([type=checkbox])[ng-form-control],textarea[ng-form-control],input:not([type=checkbox])[ng-model],textarea[ng-model]',
hostListeners: {
'change': 'onChange($event.target.value)',
'input': 'onChange($event.target.value)',
'blur': 'onTouched()'
},
hostProperties: {
'value': 'value',
'cd.control?.untouched == true': 'class.ng-untouched',
'cd.control?.touched == true': 'class.ng-touched',
'cd.control?.pristine == true': 'class.ng-pristine',
'cd.control?.dirty == true': 'class.ng-dirty',
'cd.control?.valid == true': 'class.ng-valid',
'cd.control?.valid == false': 'class.ng-invalid'
host: {
'(change)': 'onChange($event.target.value)',
'(input)': 'onChange($event.target.value)',
'(blur)': 'onTouched()',
'[value]': 'value',
'[class.ng-untouched]': 'cd.control?.untouched == true',
'[class.ng-touched]': 'cd.control?.touched == true',
'[class.ng-pristine]': 'cd.control?.pristine == true',
'[class.ng-dirty]': 'cd.control?.dirty == true',
'[class.ng-valid]': 'cd.control?.valid == true',
'[class.ng-invalid]': 'cd.control?.valid == false'
}
})
export class DefaultValueAccessor implements ControlValueAccessor {

View File

@ -60,8 +60,8 @@ const formDirectiveBinding = CONST_EXPR(
hostInjector: [formDirectiveBinding],
properties: ['form: ng-form-model'],
lifecycle: [onChange],
hostListeners: {
'submit': 'onSubmit()',
host: {
'(submit)': 'onSubmit()',
},
events: ['ngSubmit'],
exportAs: 'form'

View File

@ -17,19 +17,17 @@ import {ControlValueAccessor} from './control_value_accessor';
*/
@Directive({
selector: 'select[ng-control],select[ng-form-control],select[ng-model]',
hostListeners: {
'change': 'onChange($event.target.value)',
'input': 'onChange($event.target.value)',
'blur': 'onTouched()'
},
hostProperties: {
'value': 'value',
'cd.control?.untouched == true': 'class.ng-untouched',
'cd.control?.touched == true': 'class.ng-touched',
'cd.control?.pristine == true': 'class.ng-pristine',
'cd.control?.dirty == true': 'class.ng-dirty',
'cd.control?.valid == true': 'class.ng-valid',
'cd.control?.valid == false': 'class.ng-invalid'
host: {
'(change)': 'onChange($event.target.value)',
'(input)': 'onChange($event.target.value)',
'(blur)': 'onTouched()',
'[value]': 'value',
'[class.ng-untouched]': 'cd.control?.untouched == true',
'[class.ng-touched]': 'cd.control?.touched == true',
'[class.ng-pristine]': 'cd.control?.pristine == true',
'[class.ng-dirty]': 'cd.control?.dirty == true',
'[class.ng-valid]': 'cd.control?.valid == true',
'[class.ng-invalid]': 'cd.control?.valid == false'
}
})
export class SelectControlValueAccessor implements ControlValueAccessor {

View File

@ -16,8 +16,8 @@ const formDirectiveBinding = CONST_EXPR(new Binding(
@Directive({
selector: 'form:not([ng-no-form]):not([ng-form-model]),ng-form,[ng-form]',
hostInjector: [formDirectiveBinding],
hostListeners: {
'submit': 'onSubmit()',
host: {
'(submit)': 'onSubmit()',
},
events: ['ngSubmit'],
exportAs: 'form'

View File

@ -1,6 +1,6 @@
import {isPresent} from 'angular2/src/facade/lang';
import {isPresent, isBlank, RegExpWrapper} from 'angular2/src/facade/lang';
import {Promise} from 'angular2/src/facade/async';
import {List, Map} from 'angular2/src/facade/collection';
import {List, Map, MapWrapper, StringMap, StringMapWrapper} from 'angular2/src/facade/collection';
import {ASTWithSource} from 'angular2/change_detection';
/**
@ -123,6 +123,11 @@ export class ProtoViewDto {
}
}
// group 1: property from "[property]"
// group 2: event from "(event)"
// group 3: action from "@action"
var hostRegExp = RegExpWrapper.create('^(?:(?:\\[([^\\]]+)\\])|(?:\\(([^\\)]+)\\))|(?:@(.+)))$');
export class DirectiveMetadata {
static get DIRECTIVE_TYPE() { return 0; }
static get COMPONENT_TYPE() { return 1; }
@ -130,10 +135,6 @@ export class DirectiveMetadata {
selector: string;
compileChildren: boolean;
events: List<string>;
hostListeners: Map<string, string>;
hostProperties: Map<string, string>;
hostAttributes: Map<string, string>;
hostActions: Map<string, string>;
properties: List<string>;
readAttributes: List<string>;
type: number;
@ -144,6 +145,11 @@ export class DirectiveMetadata {
callOnAllChangesDone: boolean;
changeDetection: string;
exportAs: string;
hostListeners: Map<string, string>;
hostProperties: Map<string, string>;
hostAttributes: Map<string, string>;
hostActions: Map<string, string>;
constructor({id, selector, compileChildren, events, hostListeners, hostProperties, hostAttributes,
hostActions, properties, readAttributes, type, callOnDestroy, callOnChange,
callOnCheck, callOnInit, callOnAllChangesDone, changeDetection, exportAs}: {
@ -171,8 +177,8 @@ export class DirectiveMetadata {
this.compileChildren = isPresent(compileChildren) ? compileChildren : true;
this.events = events;
this.hostListeners = hostListeners;
this.hostProperties = hostProperties;
this.hostAttributes = hostAttributes;
this.hostProperties = hostProperties;
this.hostActions = hostActions;
this.properties = properties;
this.readAttributes = readAttributes;
@ -185,6 +191,76 @@ export class DirectiveMetadata {
this.changeDetection = changeDetection;
this.exportAs = exportAs;
}
static create({id, selector, compileChildren, events, host, properties, readAttributes, type,
callOnDestroy, callOnChange, callOnCheck, callOnInit, callOnAllChangesDone,
changeDetection, exportAs}: {
id?: string,
selector?: string,
compileChildren?: boolean,
events?: List<string>,
host?: Map<string, string>,
properties?: List<string>,
readAttributes?: List<string>,
type?: number,
callOnDestroy?: boolean,
callOnChange?: boolean,
callOnCheck?: boolean,
callOnInit?: boolean,
callOnAllChangesDone?: boolean,
changeDetection?: string,
exportAs?: string
}) {
let hostConfig = DirectiveMetadata.parseHostConfig(host);
return new DirectiveMetadata({
id: id,
selector: selector,
compileChildren: compileChildren,
events: events,
hostListeners: StringMapWrapper.get(hostConfig, 'hostListeners'),
hostProperties: StringMapWrapper.get(hostConfig, 'hostProperties'),
hostAttributes: StringMapWrapper.get(hostConfig, 'hostAttributes'),
hostActions: StringMapWrapper.get(hostConfig, 'hostActions'),
properties: properties,
readAttributes: readAttributes,
type: type,
callOnDestroy: callOnDestroy,
callOnChange: callOnChange,
callOnCheck: callOnCheck,
callOnInit: callOnInit,
callOnAllChangesDone: callOnAllChangesDone,
changeDetection: changeDetection,
exportAs: exportAs
});
}
static parseHostConfig(host?: Map<string, string>): StringMap<string, Map<string, string>> {
let hostListeners = MapWrapper.create();
let hostProperties = MapWrapper.create();
let hostAttributes = MapWrapper.create();
let hostActions = MapWrapper.create();
if (isPresent(host)) {
MapWrapper.forEach(host, (value: string, key: string) => {
var matches = RegExpWrapper.firstMatch(hostRegExp, key);
if (isBlank(matches)) {
MapWrapper.set(hostAttributes, key, value);
} else if (isPresent(matches[1])) {
MapWrapper.set(hostProperties, matches[1], value);
} else if (isPresent(matches[2])) {
MapWrapper.set(hostListeners, matches[2], value);
} else if (isPresent(matches[3])) {
MapWrapper.set(hostActions, matches[3], value);
}
});
}
return {
hostListeners: hostListeners, hostProperties: hostProperties, hostAttributes: hostAttributes,
hostActions: hostActions
}
}
}
// An opaque reference to a DomProtoView

View File

@ -85,37 +85,36 @@ import {
}
});
ListWrapper.forEach(foundDirectiveIndices, (directiveIndex) => {
var directive = this._directives[directiveIndex];
var dirMetadata = this._directives[directiveIndex];
var directiveBinderBuilder = elementBinder.bindDirective(directiveIndex);
current.compileChildren = current.compileChildren && directive.compileChildren;
if (isPresent(directive.properties)) {
ListWrapper.forEach(directive.properties, (bindConfig) => {
current.compileChildren = current.compileChildren && dirMetadata.compileChildren;
if (isPresent(dirMetadata.properties)) {
ListWrapper.forEach(dirMetadata.properties, (bindConfig) => {
this._bindDirectiveProperty(bindConfig, current, directiveBinderBuilder);
});
}
if (isPresent(directive.hostListeners)) {
MapWrapper.forEach(directive.hostListeners, (action, eventName) => {
if (isPresent(dirMetadata.hostListeners)) {
MapWrapper.forEach(dirMetadata.hostListeners, (action, eventName) => {
this._bindDirectiveEvent(eventName, action, current, directiveBinderBuilder);
});
}
if (isPresent(directive.hostActions)) {
MapWrapper.forEach(directive.hostActions, (action, actionName) => {
if (isPresent(dirMetadata.hostActions)) {
MapWrapper.forEach(dirMetadata.hostActions, (action, actionName) => {
this._bindHostAction(actionName, action, current, directiveBinderBuilder);
});
}
if (isPresent(directive.hostProperties)) {
MapWrapper.forEach(directive.hostProperties, (hostPropertyName, directivePropertyName) => {
this._bindHostProperty(hostPropertyName, directivePropertyName, current,
directiveBinderBuilder);
if (isPresent(dirMetadata.hostProperties)) {
MapWrapper.forEach(dirMetadata.hostProperties, (expression, hostPropertyName) => {
this._bindHostProperty(hostPropertyName, expression, current, directiveBinderBuilder);
});
}
if (isPresent(directive.hostAttributes)) {
MapWrapper.forEach(directive.hostAttributes, (hostAttrValue, hostAttrName) => {
if (isPresent(dirMetadata.hostAttributes)) {
MapWrapper.forEach(dirMetadata.hostAttributes, (hostAttrValue, hostAttrName) => {
this._addHostAttribute(hostAttrName, hostAttrValue, current);
});
}
if (isPresent(directive.readAttributes)) {
ListWrapper.forEach(directive.readAttributes,
if (isPresent(dirMetadata.readAttributes)) {
ListWrapper.forEach(dirMetadata.readAttributes,
(attrName) => { elementBinder.readAttribute(attrName); });
}
});
@ -176,9 +175,8 @@ import {
directiveBinderBuilder.bindHostAction(actionName, actionExpression, ast);
}
_bindHostProperty(hostPropertyName, directivePropertyName, compileElement,
directiveBinderBuilder) {
var ast = this._parser.parseBinding(directivePropertyName,
_bindHostProperty(hostPropertyName, expression, compileElement, directiveBinderBuilder) {
var ast = this._parser.parseBinding(expression,
`hostProperties of ${compileElement.elementDescription}`);
directiveBinderBuilder.bindHostProperty(hostPropertyName, ast);
}

View File

@ -11,10 +11,10 @@ export function directiveMetadataToMap(meta: DirectiveMetadata): Map<string, any
['id', meta.id],
['selector', meta.selector],
['compileChildren', meta.compileChildren],
['hostListeners', _cloneIfPresent(meta.hostListeners)],
['hostProperties', _cloneIfPresent(meta.hostProperties)],
['hostAttributes', _cloneIfPresent(meta.hostAttributes)],
['hostListeners', _cloneIfPresent(meta.hostListeners)],
['hostActions', _cloneIfPresent(meta.hostActions)],
['hostAttributes', _cloneIfPresent(meta.hostAttributes)],
['properties', _cloneIfPresent(meta.properties)],
['readAttributes', _cloneIfPresent(meta.readAttributes)],
['type', meta.type],
@ -38,8 +38,8 @@ export function directiveMetadataFromMap(map: Map<string, any>): DirectiveMetada
id:<string>MapWrapper.get(map, 'id'),
selector:<string>MapWrapper.get(map, 'selector'),
compileChildren:<boolean>MapWrapper.get(map, 'compileChildren'),
hostListeners:<Map<string, string>>_cloneIfPresent(MapWrapper.get(map, 'hostListeners')),
hostProperties:<Map<string, string>>_cloneIfPresent(MapWrapper.get(map, 'hostProperties')),
hostListeners:<Map<string, string>>_cloneIfPresent(MapWrapper.get(map, 'hostListeners')),
hostActions:<Map<string, string>>_cloneIfPresent(MapWrapper.get(map, 'hostActions')),
hostAttributes:<Map<string, string>>_cloneIfPresent(MapWrapper.get(map, 'hostAttributes')),
properties:<List<string>>_cloneIfPresent(MapWrapper.get(map, 'properties')),
@ -57,7 +57,7 @@ export function directiveMetadataFromMap(map: Map<string, any>): DirectiveMetada
/**
* Clones the [List] or [Map] `o` if it is present.
*/
function _cloneIfPresent(o) {
function _cloneIfPresent(o): any {
if (!isPresent(o)) return null;
return ListWrapper.isList(o) ? ListWrapper.clone(o) : MapWrapper.clone(o);
}

View File

@ -48,11 +48,11 @@ export class ProtoViewBuilder {
var apiElementBinders = [];
var transitiveContentTagCount = 0;
ListWrapper.forEach(this.elements, (ebb) => {
ListWrapper.forEach(this.elements, (ebb: ElementBinderBuilder) => {
var propertySetters = MapWrapper.create();
var hostActions = MapWrapper.create();
var apiDirectiveBinders = ListWrapper.map(ebb.directives, (dbb) => {
var apiDirectiveBinders = ListWrapper.map(ebb.directives, (dbb: DirectiveBuilder) => {
ebb.eventBuilder.merge(dbb.eventBuilder);
MapWrapper.forEach(dbb.hostPropertyBindings, (_, hostPropertyName) => {

View File

@ -34,7 +34,7 @@ import {Location} from './location';
selector: '[router-link]',
properties: ['route: routerLink', 'params: routerParams'],
lifecycle: [onAllChangesDone],
hostListeners: {'^click': 'onClick()'}
host: {'(^click)': 'onClick()'}
})
export class RouterLink {
private _domEl;

View File

@ -210,7 +210,7 @@ export function main() {
captureDirective(DirectiveWithProperties)
.then((renderDir) => {
expect(renderDir.hostProperties)
.toEqual(MapWrapper.createFromStringMap({'someField': 'someProp'}));
.toEqual(MapWrapper.createFromStringMap({'someProp': 'someExp'}));
async.done();
});
}));
@ -470,11 +470,11 @@ class SomeDirective {
class IgnoreChildrenDirective {
}
@Directive({hostListeners: {'someEvent': 'someAction'}})
@Directive({host: {'(someEvent)': 'someAction'}})
class DirectiveWithEvents {
}
@Directive({hostProperties: {'someField': 'someProp'}})
@Directive({host: {'[someProp]': 'someExp'}})
class DirectiveWithProperties {
}

View File

@ -303,7 +303,7 @@ class DynamicallyLoaded {
class DynamicallyLoaded2 {
}
@Component({selector: 'dummy', hostProperties: {'id': 'id'}})
@Component({selector: 'dummy', host: {'[id]': 'id'}})
@View({template: "DynamicallyLoadedWithHostProps;"})
class DynamicallyLoadedWithHostProps {
id: string;

View File

@ -432,7 +432,7 @@ export function main() {
it('should return a list of hostAction accessors', () => {
var binding = DirectiveBinding.createFromType(
HasEventEmitter, new dirAnn.Directive({hostActions: {'hostActionName': 'onAction'}}));
HasEventEmitter, new dirAnn.Directive({host: {'@hostActionName': 'onAction'}}));
var inj = createPei(null, 0, [binding]);
expect(inj.hostActionAccessors.length).toEqual(1);

View File

@ -1432,12 +1432,12 @@ class DirectiveEmitingEvent {
fireEvent(msg: string) { ObservableWrapper.callNext(this.event, msg); }
}
@Directive({selector: '[update-host-attributes]', hostAttributes: {'role': 'button'}})
@Directive({selector: '[update-host-attributes]', host: {'role': 'button'}})
@Injectable()
class DirectiveUpdatingHostAttributes {
}
@Directive({selector: '[update-host-properties]', hostProperties: {'id': 'id'}})
@Directive({selector: '[update-host-properties]', host: {'[id]': 'id'}})
@Injectable()
class DirectiveUpdatingHostProperties {
id: string;
@ -1447,7 +1447,7 @@ class DirectiveUpdatingHostProperties {
@Directive({
selector: '[update-host-actions]',
hostActions: {'setAttr': 'setAttribute("key", $action["attrValue"])'}
host: {'@setAttr': 'setAttribute("key", $action["attrValue"])'}
})
@Injectable()
class DirectiveUpdatingHostActions {
@ -1458,7 +1458,7 @@ class DirectiveUpdatingHostActions {
triggerSetAttr(attrValue) { ObservableWrapper.callNext(this.setAttr, {'attrValue': attrValue}); }
}
@Directive({selector: '[listener]', hostListeners: {'event': 'onEvent($event)'}})
@Directive({selector: '[listener]', host: {'(event)': 'onEvent($event)'}})
@Injectable()
class DirectiveListeningEvent {
msg: string;
@ -1470,11 +1470,11 @@ class DirectiveListeningEvent {
@Directive({
selector: '[listener]',
hostListeners: {
'domEvent': 'onEvent($event.type)',
'window:domEvent': 'onWindowEvent($event.type)',
'document:domEvent': 'onDocumentEvent($event.type)',
'body:domEvent': 'onBodyEvent($event.type)'
host: {
'(domEvent)': 'onEvent($event.type)',
'(window:domEvent)': 'onWindowEvent($event.type)',
'(document:domEvent)': 'onDocumentEvent($event.type)',
'(body:domEvent)': 'onBodyEvent($event.type)'
}
})
@Injectable()
@ -1489,7 +1489,7 @@ class DirectiveListeningDomEvent {
var globalCounter = 0;
@Directive(
{selector: '[listenerother]', hostListeners: {'window:domEvent': 'onEvent($event.type)'}})
{selector: '[listenerother]', host: {'(window:domEvent)': 'onEvent($event.type)'}})
@Injectable()
class DirectiveListeningDomEventOther {
eventType: string;
@ -1501,13 +1501,13 @@ class DirectiveListeningDomEventOther {
}
}
@Directive({selector: '[listenerprevent]', hostListeners: {'click': 'onEvent($event)'}})
@Directive({selector: '[listenerprevent]', host: {'(click)': 'onEvent($event)'}})
@Injectable()
class DirectiveListeningDomEventPrevent {
onEvent(event) { return false; }
}
@Directive({selector: '[listenernoprevent]', hostListeners: {'click': 'onEvent($event)'}})
@Directive({selector: '[listenernoprevent]', host: {'(click)': 'onEvent($event)'}})
@Injectable()
class DirectiveListeningDomEventNoPrevent {
onEvent(event) { return true; }

View File

@ -76,9 +76,9 @@ export function main() {
{variableBindings: MapWrapper.createFromStringMap({"exportName": "templateName"})}),
[
directiveBinding(
{metadata: new renderApi.DirectiveMetadata({exportAs: 'exportName'})}),
{metadata: renderApi.DirectiveMetadata.create({exportAs: 'exportName'})}),
directiveBinding(
{metadata: new renderApi.DirectiveMetadata({exportAs: 'otherName'})})
{metadata: renderApi.DirectiveMetadata.create({exportAs: 'otherName'})})
]);
expect(dvbs).toEqual(MapWrapper.createFromStringMap({"templateName": 0}));
@ -90,7 +90,7 @@ export function main() {
{variableBindings: MapWrapper.createFromStringMap({"$implicit": "templateName"})}),
[
directiveBinding({
metadata: new renderApi.DirectiveMetadata(
metadata: renderApi.DirectiveMetadata.create(
{exportAs: null, type: renderApi.DirectiveMetadata.COMPONENT_TYPE})
})
]);
@ -107,7 +107,7 @@ export function main() {
}),
[
directiveBinding(
{metadata: new renderApi.DirectiveMetadata({exportAs: 'exportName'})})
{metadata: renderApi.DirectiveMetadata.create({exportAs: 'exportName'})})
]);
}).toThrowError(new RegExp("Cannot find directive with exportAs = 'someInvalidName'"));
});
@ -120,9 +120,9 @@ export function main() {
}),
[
directiveBinding(
{metadata: new renderApi.DirectiveMetadata({exportAs: 'exportName'})}),
{metadata: renderApi.DirectiveMetadata.create({exportAs: 'exportName'})}),
directiveBinding(
{metadata: new renderApi.DirectiveMetadata({exportAs: 'exportName'})})
{metadata: renderApi.DirectiveMetadata.create({exportAs: 'exportName'})})
]);
}).toThrowError(new RegExp("More than one directive have exportAs = 'exportName'"));
});
@ -132,9 +132,9 @@ export function main() {
createDirectiveVariableBindings(
new renderApi.ElementBinder({variableBindings: MapWrapper.create()}), [
directiveBinding(
{metadata: new renderApi.DirectiveMetadata({exportAs: 'exportName'})}),
{metadata: renderApi.DirectiveMetadata.create({exportAs: 'exportName'})}),
directiveBinding(
{metadata: new renderApi.DirectiveMetadata({exportAs: 'exportName'})})
{metadata: renderApi.DirectiveMetadata.create({exportAs: 'exportName'})})
]);
}).not.toThrow();
});

View File

@ -733,8 +733,7 @@ export function main() {
@Directive({
selector: '[wrapped-value]',
hostListeners: {'change': 'handleOnChange($event.target.value)'},
hostProperties: {'value': 'value'}
host: {'(change)': 'handleOnChange($event.target.value)', '[value]': 'value'}
})
class WrappedValue implements ControlValueAccessor {
value;

View File

@ -0,0 +1,26 @@
import {DirectiveMetadata} from 'angular2/src/render/api';
import {MapWrapper} from 'angular2/src/facade/collection';
import {ddescribe, describe, expect, it} from 'angular2/test_lib';
export function main() {
describe('Metadata', () => {
describe('host', () => {
it('should parse host configuration', () => {
var md = DirectiveMetadata.create({
host: MapWrapper.createFromPairs([
['(event)', 'eventVal'],
['[prop]', 'propVal'],
['@action', 'actionVal'],
['attr', 'attrVal']
])
});
expect(md.hostListeners).toEqual(MapWrapper.createFromPairs([['event', 'eventVal']]));
expect(md.hostProperties).toEqual(MapWrapper.createFromPairs([['prop', 'propVal']]));
expect(md.hostActions).toEqual(MapWrapper.createFromPairs([['action', 'actionVal']]));
expect(md.hostAttributes).toEqual(MapWrapper.createFromPairs([['attr', 'attrVal']]));
});
});
});
}

View File

@ -62,7 +62,7 @@ export function runCompilerCommonTests() {
current.inheritedProtoView.bindVariable('b', 'a');
});
var dirMetadata = new DirectiveMetadata(
var dirMetadata = DirectiveMetadata.create(
{id: 'id', selector: 'CUSTOM', type: DirectiveMetadata.COMPONENT_TYPE});
compiler.compileHost(dirMetadata)
.then((protoView) => {
@ -218,5 +218,5 @@ class FakeTemplateLoader extends TemplateLoader {
}
}
var someComponent = new DirectiveMetadata(
var someComponent = DirectiveMetadata.create(
{selector: 'some-comp', id: 'someComponent', type: DirectiveMetadata.COMPONENT_TYPE});

View File

@ -111,7 +111,7 @@ export function main() {
var directiveBinding = results[0].directives[0];
var ast = MapWrapper.get(directiveBinding.hostPropertyBindings, 'hostProperty');
var ast = MapWrapper.get(directiveBinding.hostPropertyBindings, 'hostProp');
expect(ast.source).toEqual('dirProp');
});
@ -211,63 +211,63 @@ class MockStep implements CompileStep {
}
}
var someComponent = new DirectiveMetadata(
var someComponent = DirectiveMetadata.create(
{selector: 'some-comp', id: 'someComponent', type: DirectiveMetadata.COMPONENT_TYPE});
var someComponentDup = new DirectiveMetadata(
var someComponentDup = DirectiveMetadata.create(
{selector: 'some-comp', id: 'someComponentDup', type: DirectiveMetadata.COMPONENT_TYPE});
var someComponent2 = new DirectiveMetadata(
var someComponent2 = DirectiveMetadata.create(
{selector: 'some-comp2', id: 'someComponent2', type: DirectiveMetadata.COMPONENT_TYPE});
var someDirective = new DirectiveMetadata(
var someDirective = DirectiveMetadata.create(
{selector: '[some-decor]', id: 'someDirective', type: DirectiveMetadata.DIRECTIVE_TYPE});
var someDirectiveIgnoringChildren = new DirectiveMetadata({
var someDirectiveIgnoringChildren = DirectiveMetadata.create({
selector: '[some-decor-ignoring-children]',
compileChildren: false,
type: DirectiveMetadata.DIRECTIVE_TYPE
});
var decoratorWithMultipleAttrs = new DirectiveMetadata({
var decoratorWithMultipleAttrs = DirectiveMetadata.create({
selector: 'input[type=text][control]',
id: 'decoratorWithMultipleAttrs',
type: DirectiveMetadata.DIRECTIVE_TYPE
});
var someDirectiveWithProps = new DirectiveMetadata({
var someDirectiveWithProps = DirectiveMetadata.create({
selector: '[some-decor-props]',
properties: ['dirProp: elProp', 'doubleProp: elProp | double'],
readAttributes: ['some-attr']
});
var someDirectiveWithHostProperties = new DirectiveMetadata({
var someDirectiveWithHostProperties = DirectiveMetadata.create({
selector: '[some-decor-with-host-props]',
hostProperties: MapWrapper.createFromStringMap({'dirProp': 'hostProperty'})
host: MapWrapper.createFromStringMap({'[hostProp]' : 'dirProp'})
});
var someDirectiveWithHostAttributes = new DirectiveMetadata({
var someDirectiveWithHostAttributes = DirectiveMetadata.create({
selector: '[some-decor-with-host-attrs]',
hostAttributes: MapWrapper.createFromStringMap({'attr_name': 'attr_val', 'class': 'foo bar'})
host: MapWrapper.createFromStringMap({'attr_name': 'attr_val', 'class': 'foo bar'})
});
var someDirectiveWithEvents = new DirectiveMetadata({
var someDirectiveWithEvents = DirectiveMetadata.create({
selector: '[some-decor-events]',
hostListeners: MapWrapper.createFromStringMap({'click': 'doIt()'})
host: MapWrapper.createFromStringMap({'(click)': 'doIt()'})
});
var someDirectiveWithHostActions = new DirectiveMetadata({
var someDirectiveWithHostActions = DirectiveMetadata.create({
selector: '[some-decor-host-actions]',
hostActions: MapWrapper.createFromStringMap({'focus': 'focus()'})
host: MapWrapper.createFromStringMap({'@focus': 'focus()'})
});
var someDirectiveWithGlobalEvents = new DirectiveMetadata({
var someDirectiveWithGlobalEvents = DirectiveMetadata.create({
selector: '[some-decor-globalevents]',
hostListeners: MapWrapper.createFromStringMap({'window:resize': 'doItGlobal()'})
host: MapWrapper.createFromStringMap({'(window:resize)': 'doItGlobal()'})
});
var componentWithNonElementSelector = new DirectiveMetadata({
var componentWithNonElementSelector = DirectiveMetadata.create({
id: 'componentWithNonElementSelector',
selector: '[attr]',
type: DirectiveMetadata.COMPONENT_TYPE

View File

@ -8,9 +8,10 @@ export function main() {
it('directiveMetadataToMap', () => {
var someComponent = new DirectiveMetadata({
compileChildren: false,
hostListeners: MapWrapper.createFromPairs([['listenKey', 'listenVal']]),
hostProperties: MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']]),
hostActions: MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']]),
hostListeners: MapWrapper.createFromPairs([['LKey', 'LVal']]),
hostProperties: MapWrapper.createFromPairs([['PKey', 'PVal']]),
hostActions: MapWrapper.createFromPairs([['AcKey', 'AcVal']]),
hostAttributes: MapWrapper.createFromPairs([['AtKey', 'AtVal']]),
id: 'someComponent',
properties: ['propKey: propVal'],
readAttributes: ['read1', 'read2'],
@ -25,12 +26,10 @@ export function main() {
});
var map = directiveMetadataToMap(someComponent);
expect(MapWrapper.get(map, 'compileChildren')).toEqual(false);
expect(MapWrapper.get(map, 'hostListeners'))
.toEqual(MapWrapper.createFromPairs([['listenKey', 'listenVal']]));
expect(MapWrapper.get(map, 'hostProperties'))
.toEqual(MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']]));
expect(MapWrapper.get(map, 'hostActions'))
.toEqual(MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']]));
expect(MapWrapper.get(map, 'hostListeners')).toEqual(MapWrapper.createFromPairs([['LKey', 'LVal']]));
expect(MapWrapper.get(map, 'hostProperties')).toEqual(MapWrapper.createFromPairs([['PKey', 'PVal']]));
expect(MapWrapper.get(map, 'hostActions')).toEqual(MapWrapper.createFromPairs([['AcKey', 'AcVal']]));
expect(MapWrapper.get(map, 'hostAttributes')).toEqual(MapWrapper.createFromPairs([['AtKey', 'AtVal']]));
expect(MapWrapper.get(map, 'id')).toEqual('someComponent');
expect(MapWrapper.get(map, 'properties')).toEqual(['propKey: propVal']);
expect(MapWrapper.get(map, 'readAttributes')).toEqual(['read1', 'read2']);
@ -47,9 +46,10 @@ export function main() {
it('mapToDirectiveMetadata', () => {
var map = MapWrapper.createFromPairs([
['compileChildren', false],
['hostListeners', MapWrapper.createFromPairs([['testKey', 'testVal']])],
['hostProperties', MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']])],
['hostActions', MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']])],
['hostProperties', MapWrapper.createFromPairs([['PKey', 'testVal']])],
['hostListeners', MapWrapper.createFromPairs([['LKey', 'testVal']])],
['hostActions', MapWrapper.createFromPairs([['AcKey', 'testVal']])],
['hostAttributes', MapWrapper.createFromPairs([['AtKey', 'testVal']])],
['id', 'testId'],
['properties', ['propKey: propVal']],
['readAttributes', ['readTest1', 'readTest2']],
@ -64,11 +64,10 @@ export function main() {
]);
var meta = directiveMetadataFromMap(map);
expect(meta.compileChildren).toEqual(false);
expect(meta.hostListeners).toEqual(MapWrapper.createFromPairs([['testKey', 'testVal']]));
expect(meta.hostProperties)
.toEqual(MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']]));
expect(meta.hostActions)
.toEqual(MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']]));
expect(meta.hostProperties).toEqual(MapWrapper.createFromPairs([['PKey', 'testVal']]));
expect(meta.hostListeners).toEqual(MapWrapper.createFromPairs([['LKey', 'testVal']]));
expect(meta.hostActions).toEqual(MapWrapper.createFromPairs([['AcKey', 'testVal']]));
expect(meta.hostAttributes).toEqual(MapWrapper.createFromPairs([['AtKey', 'testVal']]));
expect(meta.id).toEqual('testId');
expect(meta.properties).toEqual(['propKey: propVal']);
expect(meta.readAttributes).toEqual(['readTest1', 'readTest2']);

View File

@ -180,12 +180,12 @@ export function main() {
});
}
var someComponent = new DirectiveMetadata(
var someComponent = DirectiveMetadata.create(
{id: 'someComponent', type: DirectiveMetadata.COMPONENT_TYPE, selector: 'some-comp'});
var directiveWithHostActions = new DirectiveMetadata({
var directiveWithHostActions = DirectiveMetadata.create({
id: 'withHostActions',
type: DirectiveMetadata.DIRECTIVE_TYPE,
selector: '[with-host-actions]',
hostActions: MapWrapper.createFromStringMap({'setValue': 'value = "val"'})
host: MapWrapper.createFromStringMap({'@setValue': 'value = "val"'})
});

View File

@ -399,52 +399,52 @@ export function main() {
var mainDir =
new DirectiveMetadata({selector: 'main', id: 'main', type: DirectiveMetadata.COMPONENT_TYPE});
DirectiveMetadata.create({selector: 'main', id: 'main', type: DirectiveMetadata.COMPONENT_TYPE});
var simple = new DirectiveMetadata(
var simple = DirectiveMetadata.create(
{selector: 'simple', id: 'simple', type: DirectiveMetadata.COMPONENT_TYPE});
var empty =
new DirectiveMetadata({selector: 'empty', id: 'empty', type: DirectiveMetadata.COMPONENT_TYPE});
DirectiveMetadata.create({selector: 'empty', id: 'empty', type: DirectiveMetadata.COMPONENT_TYPE});
var dynamicComponent = new DirectiveMetadata(
var dynamicComponent = DirectiveMetadata.create(
{selector: 'dynamic', id: 'dynamic', type: DirectiveMetadata.COMPONENT_TYPE});
var multipleContentTagsComponent = new DirectiveMetadata({
var multipleContentTagsComponent = DirectiveMetadata.create({
selector: 'multiple-content-tags',
id: 'multiple-content-tags',
type: DirectiveMetadata.COMPONENT_TYPE
});
var manualViewportDirective = new DirectiveMetadata(
var manualViewportDirective = DirectiveMetadata.create(
{selector: '[manual]', id: 'manual', type: DirectiveMetadata.DIRECTIVE_TYPE});
var outerWithIndirectNestedComponent = new DirectiveMetadata({
var outerWithIndirectNestedComponent = DirectiveMetadata.create({
selector: 'outer-with-indirect-nested',
id: 'outer-with-indirect-nested',
type: DirectiveMetadata.COMPONENT_TYPE
});
var outerComponent =
new DirectiveMetadata({selector: 'outer', id: 'outer', type: DirectiveMetadata.COMPONENT_TYPE});
DirectiveMetadata.create({selector: 'outer', id: 'outer', type: DirectiveMetadata.COMPONENT_TYPE});
var innerComponent =
new DirectiveMetadata({selector: 'inner', id: 'inner', type: DirectiveMetadata.COMPONENT_TYPE});
DirectiveMetadata.create({selector: 'inner', id: 'inner', type: DirectiveMetadata.COMPONENT_TYPE});
var innerInnerComponent = new DirectiveMetadata(
var innerInnerComponent = DirectiveMetadata.create(
{selector: 'innerinner', id: 'innerinner', type: DirectiveMetadata.COMPONENT_TYPE});
var conditionalContentComponent = new DirectiveMetadata({
var conditionalContentComponent = DirectiveMetadata.create({
selector: 'conditional-content',
id: 'conditional-content',
type: DirectiveMetadata.COMPONENT_TYPE
});
var autoViewportDirective = new DirectiveMetadata(
var autoViewportDirective = DirectiveMetadata.create(
{selector: '[auto]', id: '[auto]', type: DirectiveMetadata.DIRECTIVE_TYPE});
var tabComponent =
new DirectiveMetadata({selector: 'tab', id: 'tab', type: DirectiveMetadata.COMPONENT_TYPE});
DirectiveMetadata.create({selector: 'tab', id: 'tab', type: DirectiveMetadata.COMPONENT_TYPE});
var simpleTemplate = new ViewDefinition(
{componentId: 'simple', template: 'SIMPLE(<content></content>)', directives: []});

View File

@ -12,8 +12,7 @@ export class MdButton {
@Component({
selector: '[md-button][href]',
properties: ['disabled'],
hostListeners: {'click': 'onClick($event)'},
hostProperties: {'tabIndex': 'tabIndex'},
host: {'(click)': 'onClick($event)', '[tabIndex]': 'tabIndex'},
lifecycle: [onChange]
})
@View({templateUrl: 'angular2_material/src/components/button/button.html'})

View File

@ -7,12 +7,12 @@ import {NumberWrapper} from 'angular2/src/facade/lang';
@Component({
selector: 'md-checkbox',
properties: ['checked', 'disabled'],
hostListeners: {'keydown': 'onKeydown($event)'},
hostProperties: {
'tabindex': 'tabindex',
'role': 'attr.role',
'checked': 'attr.aria-checked',
'disabled': 'attr.aria-disabled'
host: {
'(keydown)': 'onKeydown($event)',
'[tabindex]': 'tabindex',
'[attr.role]': 'role',
'[attr.aria-checked]': 'checked',
'[attr.aria-disabled]': 'disabled'
}
})
@View({templateUrl: 'angular2_material/src/components/checkbox/checkbox.html', directives: []})

View File

@ -209,7 +209,7 @@ export class MdDialogConfig {
*/
@Component({
selector: 'md-dialog-container',
hostListeners: {'body:^keydown': 'documentKeypress($event)'},
host: {'(body:^keydown)': 'documentKeypress($event)'},
})
@View({
templateUrl: 'angular2_material/src/components/dialog/dialog.html',
@ -253,7 +253,7 @@ class MdDialogContent {
/** Component for the dialog "backdrop", a transparent overlay over the rest of the page. */
@Component({
selector: 'md-backdrop',
hostListeners: {'click': 'onClick()'},
host: {'(click)': 'onClick()'},
})
@View({template: ''})
class MdBackdrop {

View File

@ -218,14 +218,14 @@ export class MdGridList {
@Component({
selector: 'md-grid-tile',
properties: ['rowspan', 'colspan'],
hostProperties: {
'styleHeight': 'style.height',
'styleWidth': 'style.width',
'styleTop': 'style.top',
'styleLeft': 'style.left',
'styleMarginTop': 'style.marginTop',
'stylePaddingTop': 'style.paddingTop',
'role': 'role'
host: {
'[style.height]': 'styleHeight',
'[style.width]': 'styleWidth',
'[style.top]': 'styleTop',
'[style.left]': 'styleLeft',
'[style.marginTop]': 'styleMarginTop',
'[style.paddingTop]': 'stylePaddingTop',
'[role]': 'role'
},
lifecycle: [onDestroy, onChange]
})

View File

@ -10,8 +10,8 @@ import {ObservableWrapper, EventEmitter} from 'angular2/src/facade/async';
@Directive({
selector: 'md-input-container',
lifecycle: [onAllChangesDone],
hostProperties:
{'inputHasValue': 'class.md-input-has-value', 'inputHasFocus': 'class.md-input-focused'}
host:
{'[class.md-input-has-value]': 'inputHasValue', '[class.md-input-focused]': 'inputHasFocus'}
})
export class MdInputContainer {
// The MdInput or MdTextarea inside of this container.
@ -57,9 +57,12 @@ export class MdInputContainer {
@Directive({
selector: 'md-input-container input',
events: ['mdChange', 'mdFocusChange'],
hostProperties: {'yes': 'class.md-input'},
hostListeners:
{'input': 'updateValue($event)', 'focus': 'setHasFocus(true)', 'blur': 'setHasFocus(false)'}
host: {
'[class.md-input]': 'yes',
'(input)': 'updateValue($event)',
'(focus)': 'setHasFocus(true)',
'(blur)': 'setHasFocus(false)'
}
})
export class MdInput {
value: string;

View File

@ -7,11 +7,11 @@ import {Math} from 'angular2/src/facade/math';
selector: 'md-progress-linear',
lifecycle: [onChange],
properties: ['value', 'bufferValue'],
hostProperties: {
'role': 'attr.role',
'ariaValuemin': 'attr.aria-valuemin',
'ariaValuemax': 'attr.aria-valuemax',
'value': 'attr.aria-valuenow'
host: {
'[attr.role]': 'role',
'[attr.aria-valuemin]': 'ariaValuemin',
'[attr.aria-valuemax]': 'ariaValuemax',
'[attr.aria-valuenow]': 'value'
}
})
@View({

View File

@ -27,15 +27,13 @@ var _uniqueIdCounter: number = 0;
lifecycle: [onChange],
events: ['change'],
properties: ['disabled', 'value'],
hostListeners: {
host: {
// TODO(jelbourn): Remove ^ when event retargeting is fixed.
'^keydown': 'onKeydown($event)'
},
hostProperties: {
'tabindex': 'tabindex',
'role': 'attr.role',
'disabled': 'attr.aria-disabled',
'activedescendant': 'attr.aria-activedescendant'
'(^keydown)': 'onKeydown($event)',
'[tabindex]': 'tabindex',
'[attr.role]': 'role',
'[attr.aria-disabled]': 'disabled',
'[attr.aria-activedescendant]': 'activedescendant'
}
})
@View({templateUrl: 'angular2_material/src/components/radio/radio_group.html'})
@ -187,13 +185,13 @@ export class MdRadioGroup {
selector: 'md-radio-button',
lifecycle: [onChange],
properties: ['id', 'name', 'value', 'checked', 'disabled'],
hostListeners: {'keydown': 'onKeydown($event)'},
hostProperties: {
'id': 'id',
'tabindex': 'tabindex',
'role': 'attr.role',
'checked': 'attr.aria-checked',
'disabled': 'attr.aria-disabled'
host: {
'(keydown)': 'onKeydown($event)',
'[id]': 'id',
'[tabindex]': 'tabindex',
'[attr.role]': 'role',
'[attr.aria-checked]': 'checked',
'[attr.aria-disabled]': 'disabled'
}
})
@View({templateUrl: 'angular2_material/src/components/radio/radio_button.html', directives: []})

View File

@ -9,9 +9,12 @@ import {NumberWrapper} from 'angular2/src/facade/lang';
@Component({
selector: 'md-switch',
properties: ['checked', 'disabled'],
hostListeners: {'keydown': 'onKeydown($event)'},
hostProperties:
{'checked': 'attr.aria-checked', 'disabled_': 'attr.aria-disabled', 'role': 'attr.role'}
host: {
'(keydown)': 'onKeydown($event)',
'[attr.aria-checked]': 'checked',
'[attr.aria-disabled]': 'disabled_',
'[attr.role]': 'role'
}
})
@View({templateUrl: 'angular2_material/src/components/switcher/switch.html', directives: []})
export class MdSwitch {