feat(directive): notify directive before they get destroyed
This commit is contained in:
@@ -10,23 +10,27 @@ export class Directive {
|
||||
bind:any;
|
||||
lightDomServices:any; //List;
|
||||
implementsTypes:any; //List;
|
||||
lifecycle:any; //List
|
||||
@CONST()
|
||||
constructor({
|
||||
selector,
|
||||
bind,
|
||||
lightDomServices,
|
||||
implementsTypes
|
||||
implementsTypes,
|
||||
lifecycle
|
||||
}:{
|
||||
selector:string,
|
||||
bind:any,
|
||||
lightDomServices:List,
|
||||
implementsTypes:List
|
||||
implementsTypes:List,
|
||||
lifecycle:List
|
||||
}={})
|
||||
{
|
||||
this.selector = selector;
|
||||
this.lightDomServices = lightDomServices;
|
||||
this.implementsTypes = implementsTypes;
|
||||
this.bind = bind;
|
||||
this.lifecycle = lifecycle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,8 +41,9 @@ export class Component extends Directive {
|
||||
shadowDomServices:any; //List;
|
||||
componentServices:any; //List;
|
||||
shadowDom:any; //ShadowDomStrategy;
|
||||
lifecycle:any; //List
|
||||
|
||||
@CONST()
|
||||
@CONST()
|
||||
constructor({
|
||||
selector,
|
||||
bind,
|
||||
@@ -47,29 +52,34 @@ export class Component extends Directive {
|
||||
shadowDomServices,
|
||||
componentServices,
|
||||
implementsTypes,
|
||||
shadowDom
|
||||
shadowDom,
|
||||
lifecycle
|
||||
}:{
|
||||
selector:String,
|
||||
selector:String,
|
||||
bind:Object,
|
||||
template:TemplateConfig,
|
||||
lightDomServices:List,
|
||||
shadowDomServices:List,
|
||||
componentServices:List,
|
||||
implementsTypes:List,
|
||||
shadowDom:ShadowDomStrategy
|
||||
}={})
|
||||
shadowDom:ShadowDomStrategy,
|
||||
lifecycle:List
|
||||
}={})
|
||||
{
|
||||
super({
|
||||
selector: selector,
|
||||
bind: bind,
|
||||
lightDomServices: lightDomServices,
|
||||
implementsTypes: implementsTypes});
|
||||
implementsTypes: implementsTypes,
|
||||
lifecycle: lifecycle
|
||||
});
|
||||
|
||||
this.template = template;
|
||||
this.lightDomServices = lightDomServices;
|
||||
this.shadowDomServices = shadowDomServices;
|
||||
this.componentServices = componentServices;
|
||||
this.shadowDom = shadowDom;
|
||||
this.lifecycle = lifecycle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,12 +91,14 @@ export class Decorator extends Directive {
|
||||
bind,
|
||||
lightDomServices,
|
||||
implementsTypes,
|
||||
compileChildren = true
|
||||
lifecycle,
|
||||
compileChildren = true,
|
||||
}:{
|
||||
selector:string,
|
||||
bind:any,
|
||||
lightDomServices:List,
|
||||
implementsTypes:List,
|
||||
lifecycle:List,
|
||||
compileChildren:boolean
|
||||
}={})
|
||||
{
|
||||
@@ -95,7 +107,8 @@ export class Decorator extends Directive {
|
||||
selector: selector,
|
||||
bind: bind,
|
||||
lightDomServices: lightDomServices,
|
||||
implementsTypes: implementsTypes
|
||||
implementsTypes: implementsTypes,
|
||||
lifecycle: lifecycle
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -106,19 +119,24 @@ export class Template extends Directive {
|
||||
selector,
|
||||
bind,
|
||||
lightDomServices,
|
||||
implementsTypes
|
||||
implementsTypes,
|
||||
lifecycle
|
||||
}:{
|
||||
selector:string,
|
||||
bind:any,
|
||||
lightDomServices:List,
|
||||
implementsTypes:List
|
||||
implementsTypes:List,
|
||||
lifecycle:List
|
||||
}={})
|
||||
{
|
||||
super({
|
||||
selector: selector,
|
||||
bind: bind,
|
||||
lightDomServices: lightDomServices,
|
||||
implementsTypes: implementsTypes
|
||||
implementsTypes: implementsTypes,
|
||||
lifecycle: lifecycle
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export var onDestroy = "onDestroy";
|
||||
|
||||
@@ -3,10 +3,12 @@ import {Math} from 'facade/math';
|
||||
import {List, ListWrapper} from 'facade/collection';
|
||||
import {Injector, Key, Dependency, bind, Binding, NoProviderError, ProviderError, CyclicDependencyError} from 'di/di';
|
||||
import {Parent, Ancestor} from 'core/annotations/visibility';
|
||||
import {onDestroy} from 'core/annotations/annotations';
|
||||
import {View} from 'core/compiler/view';
|
||||
import {LightDom, SourceLightDom, DestinationLightDom} from 'core/compiler/shadow_dom_emulation/light_dom';
|
||||
import {ViewPort} from 'core/compiler/viewport';
|
||||
import {NgElement} from 'core/dom/element';
|
||||
import {Directive} from 'core/annotations/annotations'
|
||||
|
||||
var _MAX_DIRECTIVE_CONSTRUCTION_COUNTER = 10;
|
||||
|
||||
@@ -85,8 +87,9 @@ class TreeNode {
|
||||
}
|
||||
}
|
||||
|
||||
class DirectiveDependency extends Dependency {
|
||||
export class DirectiveDependency extends Dependency {
|
||||
depth:int;
|
||||
|
||||
constructor(key:Key, asPromise:boolean, lazy:boolean, properties:List, depth:int) {
|
||||
super(key, asPromise, lazy, properties);
|
||||
this.depth = depth;
|
||||
@@ -105,6 +108,28 @@ class DirectiveDependency extends Dependency {
|
||||
}
|
||||
}
|
||||
|
||||
export class DirectiveBinding extends Binding {
|
||||
callOnDestroy:boolean;
|
||||
|
||||
constructor(key:Key, factory:Function, dependencies:List, providedAsPromise:boolean, callOnDestroy:boolean) {
|
||||
super(key, factory, dependencies, providedAsPromise);
|
||||
this.callOnDestroy = callOnDestroy;
|
||||
}
|
||||
|
||||
static createFromBinding(b:Binding, annotation:Directive):Binding {
|
||||
var deps = ListWrapper.map(b.dependencies, DirectiveDependency.createFrom);
|
||||
var callOnDestroy = isPresent(annotation) && isPresent(annotation.lifecycle) ?
|
||||
ListWrapper.contains(annotation.lifecycle, onDestroy) :
|
||||
false;
|
||||
return new DirectiveBinding(b.key, b.factory, deps, b.providedAsPromise, callOnDestroy);
|
||||
}
|
||||
|
||||
static createFromType(type:Type, annotation:Directive):Binding {
|
||||
var binding = bind(type).toClass(type);
|
||||
return DirectiveBinding.createFromBinding(binding, annotation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO(rado): benchmark and consider rolling in as ElementInjector fields.
|
||||
export class PreBuiltObjects {
|
||||
@@ -205,11 +230,12 @@ export class ProtoElementInjector {
|
||||
}
|
||||
|
||||
_createBinding(bindingOrType) {
|
||||
var b = (bindingOrType instanceof Type) ?
|
||||
bind(bindingOrType).toClass(bindingOrType) :
|
||||
bindingOrType;
|
||||
var deps = ListWrapper.map(b.dependencies, DirectiveDependency.createFrom);
|
||||
return new Binding(b.key, b.factory, deps, b.providedAsPromise);
|
||||
if (bindingOrType instanceof DirectiveBinding) {
|
||||
return bindingOrType;
|
||||
} else {
|
||||
var b = bind(bindingOrType).toClass(bindingOrType);
|
||||
return DirectiveBinding.createFromBinding(b, null);
|
||||
}
|
||||
}
|
||||
|
||||
get hasBindings():boolean {
|
||||
@@ -271,6 +297,19 @@ export class ElementInjector extends TreeNode {
|
||||
this._lightDomAppInjector = null;
|
||||
this._shadowDomAppInjector = null;
|
||||
|
||||
var p = this._proto;
|
||||
|
||||
if (isPresent(p._binding0) && p._binding0.callOnDestroy) {this._obj0.onDestroy();}
|
||||
if (isPresent(p._binding1) && p._binding1.callOnDestroy) {this._obj1.onDestroy();}
|
||||
if (isPresent(p._binding2) && p._binding2.callOnDestroy) {this._obj2.onDestroy();}
|
||||
if (isPresent(p._binding3) && p._binding3.callOnDestroy) {this._obj3.onDestroy();}
|
||||
if (isPresent(p._binding4) && p._binding4.callOnDestroy) {this._obj4.onDestroy();}
|
||||
if (isPresent(p._binding5) && p._binding5.callOnDestroy) {this._obj5.onDestroy();}
|
||||
if (isPresent(p._binding6) && p._binding6.callOnDestroy) {this._obj6.onDestroy();}
|
||||
if (isPresent(p._binding7) && p._binding7.callOnDestroy) {this._obj7.onDestroy();}
|
||||
if (isPresent(p._binding8) && p._binding8.callOnDestroy) {this._obj8.onDestroy();}
|
||||
if (isPresent(p._binding9) && p._binding9.callOnDestroy) {this._obj9.onDestroy();}
|
||||
|
||||
this._obj0 = null;
|
||||
this._obj1 = null;
|
||||
this._obj2 = null;
|
||||
@@ -281,6 +320,7 @@ export class ElementInjector extends TreeNode {
|
||||
this._obj7 = null;
|
||||
this._obj8 = null;
|
||||
this._obj9 = null;
|
||||
|
||||
this._constructionCounter = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,12 @@ import {isPresent, isBlank} from 'facade/lang';
|
||||
import {ListWrapper} from 'facade/collection';
|
||||
|
||||
import {Key} from 'di/di';
|
||||
import {ProtoElementInjector, ComponentKeyMetaData} from '../element_injector';
|
||||
import {ProtoElementInjector, ComponentKeyMetaData, DirectiveBinding} from '../element_injector';
|
||||
|
||||
import {CompileStep} from './compile_step';
|
||||
import {CompileElement} from './compile_element';
|
||||
import {CompileControl} from './compile_control';
|
||||
import {DirectiveMetadata} from '../directive_metadata';
|
||||
|
||||
/**
|
||||
* Creates the ProtoElementInjectors.
|
||||
@@ -67,16 +68,20 @@ export class ProtoElementInjectorBuilder extends CompileStep {
|
||||
_collectDirectiveBindings(pipelineElement) {
|
||||
var directiveTypes = [];
|
||||
if (isPresent(pipelineElement.componentDirective)) {
|
||||
ListWrapper.push(directiveTypes, pipelineElement.componentDirective.type);
|
||||
ListWrapper.push(directiveTypes, this._createBinding(pipelineElement.componentDirective));
|
||||
}
|
||||
if (isPresent(pipelineElement.templateDirective)) {
|
||||
ListWrapper.push(directiveTypes, pipelineElement.templateDirective.type);
|
||||
ListWrapper.push(directiveTypes, this._createBinding(pipelineElement.templateDirective));
|
||||
}
|
||||
if (isPresent(pipelineElement.decoratorDirectives)) {
|
||||
for (var i=0; i<pipelineElement.decoratorDirectives.length; i++) {
|
||||
ListWrapper.push(directiveTypes, pipelineElement.decoratorDirectives[i].type);
|
||||
ListWrapper.push(directiveTypes, this._createBinding(pipelineElement.decoratorDirectives[i]));
|
||||
}
|
||||
}
|
||||
return directiveTypes;
|
||||
}
|
||||
|
||||
_createBinding(d:DirectiveMetadata): DirectiveBinding {
|
||||
return DirectiveBinding.createFromType(d.type, d.annotation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,7 +180,9 @@ export class View {
|
||||
|
||||
// elementInjectors
|
||||
for (var i = 0; i < this.elementInjectors.length; i++) {
|
||||
this.elementInjectors[i].clearDirectives();
|
||||
if (isPresent(this.elementInjectors[i])) {
|
||||
this.elementInjectors[i].clearDirectives();
|
||||
}
|
||||
}
|
||||
|
||||
// viewPorts
|
||||
|
||||
Reference in New Issue
Block a user