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

View File

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

View File

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

View File

@ -19,19 +19,17 @@ import {isBlank} from 'angular2/src/facade/lang';
@Directive({ @Directive({
selector: 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]', '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: { host: {
'change': 'onChange($event.target.value)', '(change)': 'onChange($event.target.value)',
'input': 'onChange($event.target.value)', '(input)': 'onChange($event.target.value)',
'blur': 'onTouched()' '(blur)': 'onTouched()',
}, '[value]': 'value',
hostProperties: { '[class.ng-untouched]': 'cd.control?.untouched == true',
'value': 'value', '[class.ng-touched]': 'cd.control?.touched == true',
'cd.control?.untouched == true': 'class.ng-untouched', '[class.ng-pristine]': 'cd.control?.pristine == true',
'cd.control?.touched == true': 'class.ng-touched', '[class.ng-dirty]': 'cd.control?.dirty == true',
'cd.control?.pristine == true': 'class.ng-pristine', '[class.ng-valid]': 'cd.control?.valid == true',
'cd.control?.dirty == true': 'class.ng-dirty', '[class.ng-invalid]': 'cd.control?.valid == false'
'cd.control?.valid == true': 'class.ng-valid',
'cd.control?.valid == false': 'class.ng-invalid'
} }
}) })
export class DefaultValueAccessor implements ControlValueAccessor { export class DefaultValueAccessor implements ControlValueAccessor {

View File

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

View File

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

View File

@ -16,8 +16,8 @@ const formDirectiveBinding = CONST_EXPR(new Binding(
@Directive({ @Directive({
selector: 'form:not([ng-no-form]):not([ng-form-model]),ng-form,[ng-form]', selector: 'form:not([ng-no-form]):not([ng-form-model]),ng-form,[ng-form]',
hostInjector: [formDirectiveBinding], hostInjector: [formDirectiveBinding],
hostListeners: { host: {
'submit': 'onSubmit()', '(submit)': 'onSubmit()',
}, },
events: ['ngSubmit'], events: ['ngSubmit'],
exportAs: 'form' 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 {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'; 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 { export class DirectiveMetadata {
static get DIRECTIVE_TYPE() { return 0; } static get DIRECTIVE_TYPE() { return 0; }
static get COMPONENT_TYPE() { return 1; } static get COMPONENT_TYPE() { return 1; }
@ -130,10 +135,6 @@ export class DirectiveMetadata {
selector: string; selector: string;
compileChildren: boolean; compileChildren: boolean;
events: List<string>; events: List<string>;
hostListeners: Map<string, string>;
hostProperties: Map<string, string>;
hostAttributes: Map<string, string>;
hostActions: Map<string, string>;
properties: List<string>; properties: List<string>;
readAttributes: List<string>; readAttributes: List<string>;
type: number; type: number;
@ -144,6 +145,11 @@ export class DirectiveMetadata {
callOnAllChangesDone: boolean; callOnAllChangesDone: boolean;
changeDetection: string; changeDetection: string;
exportAs: 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, constructor({id, selector, compileChildren, events, hostListeners, hostProperties, hostAttributes,
hostActions, properties, readAttributes, type, callOnDestroy, callOnChange, hostActions, properties, readAttributes, type, callOnDestroy, callOnChange,
callOnCheck, callOnInit, callOnAllChangesDone, changeDetection, exportAs}: { callOnCheck, callOnInit, callOnAllChangesDone, changeDetection, exportAs}: {
@ -171,8 +177,8 @@ export class DirectiveMetadata {
this.compileChildren = isPresent(compileChildren) ? compileChildren : true; this.compileChildren = isPresent(compileChildren) ? compileChildren : true;
this.events = events; this.events = events;
this.hostListeners = hostListeners; this.hostListeners = hostListeners;
this.hostProperties = hostProperties;
this.hostAttributes = hostAttributes; this.hostAttributes = hostAttributes;
this.hostProperties = hostProperties;
this.hostActions = hostActions; this.hostActions = hostActions;
this.properties = properties; this.properties = properties;
this.readAttributes = readAttributes; this.readAttributes = readAttributes;
@ -185,6 +191,76 @@ export class DirectiveMetadata {
this.changeDetection = changeDetection; this.changeDetection = changeDetection;
this.exportAs = exportAs; 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 // An opaque reference to a DomProtoView

View File

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

View File

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

View File

@ -48,11 +48,11 @@ export class ProtoViewBuilder {
var apiElementBinders = []; var apiElementBinders = [];
var transitiveContentTagCount = 0; var transitiveContentTagCount = 0;
ListWrapper.forEach(this.elements, (ebb) => { ListWrapper.forEach(this.elements, (ebb: ElementBinderBuilder) => {
var propertySetters = MapWrapper.create(); var propertySetters = MapWrapper.create();
var hostActions = 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); ebb.eventBuilder.merge(dbb.eventBuilder);
MapWrapper.forEach(dbb.hostPropertyBindings, (_, hostPropertyName) => { MapWrapper.forEach(dbb.hostPropertyBindings, (_, hostPropertyName) => {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -733,8 +733,7 @@ export function main() {
@Directive({ @Directive({
selector: '[wrapped-value]', selector: '[wrapped-value]',
hostListeners: {'change': 'handleOnChange($event.target.value)'}, host: {'(change)': 'handleOnChange($event.target.value)', '[value]': 'value'}
hostProperties: {'value': 'value'}
}) })
class WrappedValue implements ControlValueAccessor { class WrappedValue implements ControlValueAccessor {
value; 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'); current.inheritedProtoView.bindVariable('b', 'a');
}); });
var dirMetadata = new DirectiveMetadata( var dirMetadata = DirectiveMetadata.create(
{id: 'id', selector: 'CUSTOM', type: DirectiveMetadata.COMPONENT_TYPE}); {id: 'id', selector: 'CUSTOM', type: DirectiveMetadata.COMPONENT_TYPE});
compiler.compileHost(dirMetadata) compiler.compileHost(dirMetadata)
.then((protoView) => { .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}); {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 directiveBinding = results[0].directives[0];
var ast = MapWrapper.get(directiveBinding.hostPropertyBindings, 'hostProperty'); var ast = MapWrapper.get(directiveBinding.hostPropertyBindings, 'hostProp');
expect(ast.source).toEqual('dirProp'); 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}); {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}); {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}); {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}); {selector: '[some-decor]', id: 'someDirective', type: DirectiveMetadata.DIRECTIVE_TYPE});
var someDirectiveIgnoringChildren = new DirectiveMetadata({ var someDirectiveIgnoringChildren = DirectiveMetadata.create({
selector: '[some-decor-ignoring-children]', selector: '[some-decor-ignoring-children]',
compileChildren: false, compileChildren: false,
type: DirectiveMetadata.DIRECTIVE_TYPE type: DirectiveMetadata.DIRECTIVE_TYPE
}); });
var decoratorWithMultipleAttrs = new DirectiveMetadata({ var decoratorWithMultipleAttrs = DirectiveMetadata.create({
selector: 'input[type=text][control]', selector: 'input[type=text][control]',
id: 'decoratorWithMultipleAttrs', id: 'decoratorWithMultipleAttrs',
type: DirectiveMetadata.DIRECTIVE_TYPE type: DirectiveMetadata.DIRECTIVE_TYPE
}); });
var someDirectiveWithProps = new DirectiveMetadata({ var someDirectiveWithProps = DirectiveMetadata.create({
selector: '[some-decor-props]', selector: '[some-decor-props]',
properties: ['dirProp: elProp', 'doubleProp: elProp | double'], properties: ['dirProp: elProp', 'doubleProp: elProp | double'],
readAttributes: ['some-attr'] readAttributes: ['some-attr']
}); });
var someDirectiveWithHostProperties = new DirectiveMetadata({ var someDirectiveWithHostProperties = DirectiveMetadata.create({
selector: '[some-decor-with-host-props]', 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]', 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]', 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]', 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]', 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', id: 'componentWithNonElementSelector',
selector: '[attr]', selector: '[attr]',
type: DirectiveMetadata.COMPONENT_TYPE type: DirectiveMetadata.COMPONENT_TYPE

View File

@ -8,9 +8,10 @@ export function main() {
it('directiveMetadataToMap', () => { it('directiveMetadataToMap', () => {
var someComponent = new DirectiveMetadata({ var someComponent = new DirectiveMetadata({
compileChildren: false, compileChildren: false,
hostListeners: MapWrapper.createFromPairs([['listenKey', 'listenVal']]), hostListeners: MapWrapper.createFromPairs([['LKey', 'LVal']]),
hostProperties: MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']]), hostProperties: MapWrapper.createFromPairs([['PKey', 'PVal']]),
hostActions: MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']]), hostActions: MapWrapper.createFromPairs([['AcKey', 'AcVal']]),
hostAttributes: MapWrapper.createFromPairs([['AtKey', 'AtVal']]),
id: 'someComponent', id: 'someComponent',
properties: ['propKey: propVal'], properties: ['propKey: propVal'],
readAttributes: ['read1', 'read2'], readAttributes: ['read1', 'read2'],
@ -25,12 +26,10 @@ export function main() {
}); });
var map = directiveMetadataToMap(someComponent); var map = directiveMetadataToMap(someComponent);
expect(MapWrapper.get(map, 'compileChildren')).toEqual(false); expect(MapWrapper.get(map, 'compileChildren')).toEqual(false);
expect(MapWrapper.get(map, 'hostListeners')) expect(MapWrapper.get(map, 'hostListeners')).toEqual(MapWrapper.createFromPairs([['LKey', 'LVal']]));
.toEqual(MapWrapper.createFromPairs([['listenKey', 'listenVal']])); expect(MapWrapper.get(map, 'hostProperties')).toEqual(MapWrapper.createFromPairs([['PKey', 'PVal']]));
expect(MapWrapper.get(map, 'hostProperties')) expect(MapWrapper.get(map, 'hostActions')).toEqual(MapWrapper.createFromPairs([['AcKey', 'AcVal']]));
.toEqual(MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']])); expect(MapWrapper.get(map, 'hostAttributes')).toEqual(MapWrapper.createFromPairs([['AtKey', 'AtVal']]));
expect(MapWrapper.get(map, 'hostActions'))
.toEqual(MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']]));
expect(MapWrapper.get(map, 'id')).toEqual('someComponent'); expect(MapWrapper.get(map, 'id')).toEqual('someComponent');
expect(MapWrapper.get(map, 'properties')).toEqual(['propKey: propVal']); expect(MapWrapper.get(map, 'properties')).toEqual(['propKey: propVal']);
expect(MapWrapper.get(map, 'readAttributes')).toEqual(['read1', 'read2']); expect(MapWrapper.get(map, 'readAttributes')).toEqual(['read1', 'read2']);
@ -47,9 +46,10 @@ export function main() {
it('mapToDirectiveMetadata', () => { it('mapToDirectiveMetadata', () => {
var map = MapWrapper.createFromPairs([ var map = MapWrapper.createFromPairs([
['compileChildren', false], ['compileChildren', false],
['hostListeners', MapWrapper.createFromPairs([['testKey', 'testVal']])], ['hostProperties', MapWrapper.createFromPairs([['PKey', 'testVal']])],
['hostProperties', MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']])], ['hostListeners', MapWrapper.createFromPairs([['LKey', 'testVal']])],
['hostActions', MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']])], ['hostActions', MapWrapper.createFromPairs([['AcKey', 'testVal']])],
['hostAttributes', MapWrapper.createFromPairs([['AtKey', 'testVal']])],
['id', 'testId'], ['id', 'testId'],
['properties', ['propKey: propVal']], ['properties', ['propKey: propVal']],
['readAttributes', ['readTest1', 'readTest2']], ['readAttributes', ['readTest1', 'readTest2']],
@ -64,11 +64,10 @@ export function main() {
]); ]);
var meta = directiveMetadataFromMap(map); var meta = directiveMetadataFromMap(map);
expect(meta.compileChildren).toEqual(false); expect(meta.compileChildren).toEqual(false);
expect(meta.hostListeners).toEqual(MapWrapper.createFromPairs([['testKey', 'testVal']])); expect(meta.hostProperties).toEqual(MapWrapper.createFromPairs([['PKey', 'testVal']]));
expect(meta.hostProperties) expect(meta.hostListeners).toEqual(MapWrapper.createFromPairs([['LKey', 'testVal']]));
.toEqual(MapWrapper.createFromPairs([['hostPropKey', 'hostPropVal']])); expect(meta.hostActions).toEqual(MapWrapper.createFromPairs([['AcKey', 'testVal']]));
expect(meta.hostActions) expect(meta.hostAttributes).toEqual(MapWrapper.createFromPairs([['AtKey', 'testVal']]));
.toEqual(MapWrapper.createFromPairs([['hostActionKey', 'hostActionVal']]));
expect(meta.id).toEqual('testId'); expect(meta.id).toEqual('testId');
expect(meta.properties).toEqual(['propKey: propVal']); expect(meta.properties).toEqual(['propKey: propVal']);
expect(meta.readAttributes).toEqual(['readTest1', 'readTest2']); 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'}); {id: 'someComponent', type: DirectiveMetadata.COMPONENT_TYPE, selector: 'some-comp'});
var directiveWithHostActions = new DirectiveMetadata({ var directiveWithHostActions = DirectiveMetadata.create({
id: 'withHostActions', id: 'withHostActions',
type: DirectiveMetadata.DIRECTIVE_TYPE, type: DirectiveMetadata.DIRECTIVE_TYPE,
selector: '[with-host-actions]', 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 = 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}); {selector: 'simple', id: 'simple', type: DirectiveMetadata.COMPONENT_TYPE});
var empty = 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}); {selector: 'dynamic', id: 'dynamic', type: DirectiveMetadata.COMPONENT_TYPE});
var multipleContentTagsComponent = new DirectiveMetadata({ var multipleContentTagsComponent = DirectiveMetadata.create({
selector: 'multiple-content-tags', selector: 'multiple-content-tags',
id: 'multiple-content-tags', id: 'multiple-content-tags',
type: DirectiveMetadata.COMPONENT_TYPE type: DirectiveMetadata.COMPONENT_TYPE
}); });
var manualViewportDirective = new DirectiveMetadata( var manualViewportDirective = DirectiveMetadata.create(
{selector: '[manual]', id: 'manual', type: DirectiveMetadata.DIRECTIVE_TYPE}); {selector: '[manual]', id: 'manual', type: DirectiveMetadata.DIRECTIVE_TYPE});
var outerWithIndirectNestedComponent = new DirectiveMetadata({ var outerWithIndirectNestedComponent = DirectiveMetadata.create({
selector: 'outer-with-indirect-nested', selector: 'outer-with-indirect-nested',
id: 'outer-with-indirect-nested', id: 'outer-with-indirect-nested',
type: DirectiveMetadata.COMPONENT_TYPE type: DirectiveMetadata.COMPONENT_TYPE
}); });
var outerComponent = var outerComponent =
new DirectiveMetadata({selector: 'outer', id: 'outer', type: DirectiveMetadata.COMPONENT_TYPE}); DirectiveMetadata.create({selector: 'outer', id: 'outer', type: DirectiveMetadata.COMPONENT_TYPE});
var innerComponent = 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}); {selector: 'innerinner', id: 'innerinner', type: DirectiveMetadata.COMPONENT_TYPE});
var conditionalContentComponent = new DirectiveMetadata({ var conditionalContentComponent = DirectiveMetadata.create({
selector: 'conditional-content', selector: 'conditional-content',
id: 'conditional-content', id: 'conditional-content',
type: DirectiveMetadata.COMPONENT_TYPE type: DirectiveMetadata.COMPONENT_TYPE
}); });
var autoViewportDirective = new DirectiveMetadata( var autoViewportDirective = DirectiveMetadata.create(
{selector: '[auto]', id: '[auto]', type: DirectiveMetadata.DIRECTIVE_TYPE}); {selector: '[auto]', id: '[auto]', type: DirectiveMetadata.DIRECTIVE_TYPE});
var tabComponent = 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( var simpleTemplate = new ViewDefinition(
{componentId: 'simple', template: 'SIMPLE(<content></content>)', directives: []}); {componentId: 'simple', template: 'SIMPLE(<content></content>)', directives: []});

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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