feat(core): add support for @Property and @Event decorators

Example:

@Directive({selector: 'my-selector'})
class MyDirective {
  @Property() prop;
  @Property('el-prop') prop2;
  @Event() event;
  @Event('el-event') event2;
}

Closes #3992
This commit is contained in:
vsavkin
2015-09-03 15:10:48 -07:00
committed by Victor Savkin
parent 337ce21149
commit 896add7d77
19 changed files with 511 additions and 89 deletions

View File

@ -1,6 +1,12 @@
import {resolveForwardRef, Injectable} from 'angular2/di';
import {Type, isPresent, BaseException, stringify} from 'angular2/src/core/facade/lang';
import {DirectiveMetadata} from 'angular2/metadata';
import {ListWrapper, StringMapWrapper} from 'angular2/src/core/facade/collection';
import {
DirectiveMetadata,
ComponentMetadata,
PropertyMetadata,
EventMetadata
} from 'angular2/metadata';
import {reflector} from 'angular2/src/core/reflection/reflection';
/**
@ -16,15 +22,78 @@ export class DirectiveResolver {
* Return {@link DirectiveMetadata} for a given `Type`.
*/
resolve(type: Type): DirectiveMetadata {
var annotations = reflector.annotations(resolveForwardRef(type));
if (isPresent(annotations)) {
for (var i = 0; i < annotations.length; i++) {
var annotation = annotations[i];
if (annotation instanceof DirectiveMetadata) {
return annotation;
var typeMetadata = reflector.annotations(resolveForwardRef(type));
if (isPresent(typeMetadata)) {
for (var i = 0; i < typeMetadata.length; i++) {
var metadata = typeMetadata[i];
if (metadata instanceof DirectiveMetadata) {
var propertyMetadata = reflector.propMetadata(type);
return this._mergeWithPropertyMetadata(metadata, propertyMetadata);
}
}
}
throw new BaseException(`No Directive annotation found on ${stringify(type)}`);
}
private _mergeWithPropertyMetadata(dm: DirectiveMetadata,
propertyMetadata:
StringMap<string, any[]>): DirectiveMetadata {
var properties = [];
var events = [];
StringMapWrapper.forEach(propertyMetadata, (metadata: any[], propName: string) => {
metadata.forEach(a => {
if (a instanceof PropertyMetadata) {
if (isPresent(a.bindingPropertyName)) {
properties.push(`${propName}: ${a.bindingPropertyName}`);
} else {
properties.push(propName);
}
}
if (a instanceof EventMetadata) {
if (isPresent(a.bindingPropertyName)) {
events.push(`${propName}: ${a.bindingPropertyName}`);
} else {
events.push(propName);
}
}
});
});
return this._merge(dm, properties, events);
}
private _merge(dm: DirectiveMetadata, properties: string[], events: string[]): DirectiveMetadata {
var mergedProperties =
isPresent(dm.properties) ? ListWrapper.concat(dm.properties, properties) : properties;
var mergedEvents = isPresent(dm.events) ? ListWrapper.concat(dm.events, events) : events;
if (dm instanceof ComponentMetadata) {
return new ComponentMetadata({
selector: dm.selector,
properties: mergedProperties,
events: mergedEvents,
host: dm.host,
lifecycle: dm.lifecycle,
bindings: dm.bindings,
exportAs: dm.exportAs,
compileChildren: dm.compileChildren,
changeDetection: dm.changeDetection,
viewBindings: dm.viewBindings
});
} else {
return new DirectiveMetadata({
selector: dm.selector,
properties: mergedProperties,
events: mergedEvents,
host: dm.host,
lifecycle: dm.lifecycle,
bindings: dm.bindings,
exportAs: dm.exportAs,
compileChildren: dm.compileChildren
});
}
}
}