feat(core): added support for detecting lifecycle events based on interfaces
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import {CONST, normalizeBlank, isPresent, CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
import {ListWrapper, List} from 'angular2/src/facade/collection';
|
||||
import {CONST, CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
import {List} from 'angular2/src/facade/collection';
|
||||
import {Injectable} from 'angular2/src/di/annotations_impl';
|
||||
import {DEFAULT} from 'angular2/change_detection';
|
||||
|
||||
@@ -778,15 +778,6 @@ export class Directive extends Injectable {
|
||||
this.compileChildren = compileChildren;
|
||||
this.hostInjector = hostInjector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a directive participates in a given `LifecycleEvent`.
|
||||
*
|
||||
* See {@link onChange}, {@link onDestroy}, {@link onAllChangesDone} for details.
|
||||
*/
|
||||
hasLifecycleHook(hook: LifecycleEvent): boolean {
|
||||
return isPresent(this.lifecycle) ? ListWrapper.contains(this.lifecycle, hook) : false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import 'package:angular2/src/core/annotations_impl/annotations.dart';
|
||||
import 'package:angular2/src/core/compiler/interfaces.dart';
|
||||
import 'package:angular2/src/reflection/reflection.dart';
|
||||
|
||||
bool hasLifecycleHook(LifecycleEvent e, type, Directive annotation) {
|
||||
if (annotation.lifecycle != null) {
|
||||
return annotation.lifecycle.contains(e);
|
||||
} else {
|
||||
if (type is! Type) return false;
|
||||
|
||||
final List interfaces = reflector.interfaces(type);
|
||||
var interface;
|
||||
|
||||
if (e == onChange) {
|
||||
interface = OnChange;
|
||||
|
||||
} else if (e == onDestroy) {
|
||||
interface = OnDestroy;
|
||||
|
||||
} else if (e == onAllChangesDone) {
|
||||
interface = OnAllChangesDone;
|
||||
}
|
||||
|
||||
return interfaces.contains(interface);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import {Type, isPresent} from 'angular2/src/facade/lang';
|
||||
import {LifecycleEvent, Directive} from 'angular2/src/core/annotations_impl/annotations';
|
||||
|
||||
export function hasLifecycleHook(e: LifecycleEvent, type, annotation: Directive): boolean {
|
||||
if (isPresent(annotation.lifecycle)) {
|
||||
return annotation.lifecycle.indexOf(e) !== -1;
|
||||
} else {
|
||||
if (!(type instanceof Type)) return false;
|
||||
return e.name in(<any>type).prototype;
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
onDestroy,
|
||||
onAllChangesDone
|
||||
} from 'angular2/src/core/annotations_impl/annotations';
|
||||
import {hasLifecycleHook} from './directive_lifecycle_reflector';
|
||||
import {ChangeDetector, ChangeDetectorRef} from 'angular2/change_detection';
|
||||
import {QueryList} from './query_list';
|
||||
import {reflector} from 'angular2/src/reflection/reflection';
|
||||
@@ -282,7 +283,6 @@ export class DirectiveBinding extends ResolvedBinding {
|
||||
var resolvedViewInjectables = ann instanceof Component && isPresent(ann.viewInjector) ?
|
||||
resolveBindings(ann.viewInjector) :
|
||||
[];
|
||||
|
||||
var metadata = new DirectiveMetadata({
|
||||
id: stringify(rb.key.token),
|
||||
type: ann instanceof
|
||||
@@ -300,9 +300,11 @@ export class DirectiveBinding extends ResolvedBinding {
|
||||
null,
|
||||
properties: isPresent(ann.properties) ? MapWrapper.createFromStringMap(ann.properties) : null,
|
||||
readAttributes: DirectiveBinding._readAttributes(deps),
|
||||
callOnDestroy: ann.hasLifecycleHook(onDestroy),
|
||||
callOnChange: ann.hasLifecycleHook(onChange),
|
||||
callOnAllChangesDone: ann.hasLifecycleHook(onAllChangesDone),
|
||||
|
||||
callOnDestroy: hasLifecycleHook(onDestroy, rb.key.token, ann),
|
||||
callOnChange: hasLifecycleHook(onChange, rb.key.token, ann),
|
||||
callOnAllChangesDone: hasLifecycleHook(onAllChangesDone, rb.key.token, ann),
|
||||
|
||||
changeDetection: ann instanceof
|
||||
Component ? ann.changeDetection : null
|
||||
});
|
||||
|
||||
@@ -12,6 +12,7 @@ export interface OnChange { onChange(changes: StringMap<string, any>): void; }
|
||||
export interface OnDestroy { onDestroy(): void; }
|
||||
|
||||
/**
|
||||
* Defines lifecycle method [onAllChangesDone ] called when the bindings of all its children have been changed.
|
||||
* Defines lifecycle method [onAllChangesDone ] called when the bindings of all its children have
|
||||
* been changed.
|
||||
*/
|
||||
export interface OnAllChangesDone { onAllChangesDone (): void; }
|
||||
export interface OnAllChangesDone { onAllChangesDone(): void; }
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
library reflection.reflection_capabilities;
|
||||
|
||||
import 'reflection.dart';
|
||||
import 'package:angular2/src/facade/lang.dart';
|
||||
import 'types.dart';
|
||||
import 'dart:mirrors';
|
||||
|
||||
@@ -97,9 +97,7 @@ export class ReflectionCapabilities {
|
||||
return [];
|
||||
}
|
||||
|
||||
interfaces(type): List<any> {
|
||||
throw new BaseException("JavaScript does not support interfaces");
|
||||
}
|
||||
interfaces(type): List<any> { throw new BaseException("JavaScript does not support interfaces"); }
|
||||
|
||||
getter(name: string): GetterFn { return new Function('o', 'return o.' + name + ';'); }
|
||||
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import {Type, isPresent, stringify, BaseException} from 'angular2/src/facade/lang';
|
||||
import {List, ListWrapper, Map, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||
import {
|
||||
List,
|
||||
ListWrapper,
|
||||
Map,
|
||||
MapWrapper,
|
||||
StringMap,
|
||||
StringMapWrapper
|
||||
} from 'angular2/src/facade/collection';
|
||||
import {SetterFn, GetterFn, MethodFn} from './types';
|
||||
export {SetterFn, GetterFn, MethodFn} from './types';
|
||||
|
||||
export class Reflector {
|
||||
_typeInfo: Map<Type, any>;
|
||||
@@ -18,7 +24,7 @@ export class Reflector {
|
||||
this.reflectionCapabilities = reflectionCapabilities;
|
||||
}
|
||||
|
||||
registerType(type: Type, typeInfo: Map<Type, any>): void {
|
||||
registerType(type: Type, typeInfo: StringMap<string, any>): void {
|
||||
MapWrapper.set(this._typeInfo, type, typeInfo);
|
||||
}
|
||||
|
||||
@@ -29,32 +35,32 @@ export class Reflector {
|
||||
registerMethods(methods: Map<string, MethodFn>): void { _mergeMaps(this._methods, methods); }
|
||||
|
||||
factory(type: Type): Function {
|
||||
if (MapWrapper.contains(this._typeInfo, type)) {
|
||||
return MapWrapper.get(this._typeInfo, type)["factory"];
|
||||
if (this._containsTypeInfo(type)) {
|
||||
return this._getTypeInfoField(type, "factory", null);
|
||||
} else {
|
||||
return this.reflectionCapabilities.factory(type);
|
||||
}
|
||||
}
|
||||
|
||||
parameters(typeOfFunc): List<any> {
|
||||
if (MapWrapper.contains(this._typeInfo, typeOfFunc)) {
|
||||
return MapWrapper.get(this._typeInfo, typeOfFunc)["parameters"];
|
||||
parameters(typeOrFunc): List<any> {
|
||||
if (MapWrapper.contains(this._typeInfo, typeOrFunc)) {
|
||||
return this._getTypeInfoField(typeOrFunc, "parameters", []);
|
||||
} else {
|
||||
return this.reflectionCapabilities.parameters(typeOfFunc);
|
||||
return this.reflectionCapabilities.parameters(typeOrFunc);
|
||||
}
|
||||
}
|
||||
|
||||
annotations(typeOfFunc): List<any> {
|
||||
if (MapWrapper.contains(this._typeInfo, typeOfFunc)) {
|
||||
return MapWrapper.get(this._typeInfo, typeOfFunc)["annotations"];
|
||||
annotations(typeOrFunc): List<any> {
|
||||
if (MapWrapper.contains(this._typeInfo, typeOrFunc)) {
|
||||
return this._getTypeInfoField(typeOrFunc, "annotations", []);
|
||||
} else {
|
||||
return this.reflectionCapabilities.annotations(typeOfFunc);
|
||||
return this.reflectionCapabilities.annotations(typeOrFunc);
|
||||
}
|
||||
}
|
||||
|
||||
interfaces(type): List<any> {
|
||||
if (MapWrapper.contains(this._typeInfo, type)) {
|
||||
return MapWrapper.get(this._typeInfo, type)["interfaces"];
|
||||
return this._getTypeInfoField(type, "interfaces", []);
|
||||
} else {
|
||||
return this.reflectionCapabilities.interfaces(type);
|
||||
}
|
||||
@@ -83,6 +89,13 @@ export class Reflector {
|
||||
return this.reflectionCapabilities.method(name);
|
||||
}
|
||||
}
|
||||
|
||||
_getTypeInfoField(typeOrFunc, key, defaultValue) {
|
||||
var res = MapWrapper.get(this._typeInfo, typeOrFunc)[key];
|
||||
return isPresent(res) ? res : defaultValue;
|
||||
}
|
||||
|
||||
_containsTypeInfo(typeOrFunc) { return MapWrapper.contains(this._typeInfo, typeOrFunc); }
|
||||
}
|
||||
|
||||
function _mergeMaps(target: Map<any, any>, config: Map<string, Function>): void {
|
||||
|
||||
Reference in New Issue
Block a user