fix(dynamic_component_loader): implemented dispose for dynamically-loaded components
This commit is contained in:
parent
9613772455
commit
21dcfc89e9
|
@ -43,7 +43,7 @@ export class DynamicComponentLoader {
|
||||||
this._viewManager.createDynamicComponentView(location, componentProtoViewRef, binding,
|
this._viewManager.createDynamicComponentView(location, componentProtoViewRef, binding,
|
||||||
injector);
|
injector);
|
||||||
var component = this._viewManager.getComponent(location);
|
var component = this._viewManager.getComponent(location);
|
||||||
var dispose = () => { throw new BaseException("Not implemented"); };
|
var dispose = () => { this._viewManager.destroyDynamicComponent(location); };
|
||||||
return new ComponentRef(location, component, dispose);
|
return new ComponentRef(location, component, dispose);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -688,22 +688,20 @@ export class ElementInjector extends TreeNode<ElementInjector> {
|
||||||
this._preBuiltObjects = null;
|
this._preBuiltObjects = null;
|
||||||
this._lightDomAppInjector = null;
|
this._lightDomAppInjector = null;
|
||||||
this._shadowDomAppInjector = null;
|
this._shadowDomAppInjector = null;
|
||||||
|
|
||||||
this._strategy.callOnDestroy();
|
this._strategy.callOnDestroy();
|
||||||
|
this.destroyDynamicComponent();
|
||||||
if (isPresent(this._dynamicallyCreatedComponentBinding) &&
|
|
||||||
this._dynamicallyCreatedComponentBinding.callOnDestroy) {
|
|
||||||
this._dynamicallyCreatedComponent.onDestroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._strategy.clearInstances();
|
this._strategy.clearInstances();
|
||||||
|
|
||||||
this._dynamicallyCreatedComponent = null;
|
|
||||||
this._dynamicallyCreatedComponentBinding = null;
|
|
||||||
|
|
||||||
this._constructionCounter = 0;
|
this._constructionCounter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
destroyDynamicComponent(): void {
|
||||||
|
if (isPresent(this._dynamicallyCreatedComponentBinding) &&
|
||||||
|
this._dynamicallyCreatedComponentBinding.callOnDestroy) {
|
||||||
|
this._dynamicallyCreatedComponent.onDestroy();
|
||||||
|
this._dynamicallyCreatedComponentBinding = null;
|
||||||
|
this._dynamicallyCreatedComponent = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hydrate(injector: Injector, host: ElementInjector, preBuiltObjects: PreBuiltObjects): void {
|
hydrate(injector: Injector, host: ElementInjector, preBuiltObjects: PreBuiltObjects): void {
|
||||||
var p = this._proto;
|
var p = this._proto;
|
||||||
|
|
|
@ -133,6 +133,14 @@ export class AppViewManager {
|
||||||
this._destroyFreeEmbeddedView(parentView, boundElementIndex, internalView(viewRef));
|
this._destroyFreeEmbeddedView(parentView, boundElementIndex, internalView(viewRef));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
destroyDynamicComponent(location: ElementRef) {
|
||||||
|
var hostView = internalView(location.parentView);
|
||||||
|
var ei = hostView.elementInjectors[location.boundElementIndex];
|
||||||
|
var componentView = hostView.componentChildViews[location.boundElementIndex];
|
||||||
|
ei.destroyDynamicComponent();
|
||||||
|
this._destroyComponentView(hostView, location.boundElementIndex, componentView);
|
||||||
|
}
|
||||||
|
|
||||||
createViewInContainer(viewContainerLocation: ElementRef, atIndex: number,
|
createViewInContainer(viewContainerLocation: ElementRef, atIndex: number,
|
||||||
protoViewRef: ProtoViewRef, context: ElementRef = null,
|
protoViewRef: ProtoViewRef, context: ElementRef = null,
|
||||||
injector: Injector = null): ViewRef {
|
injector: Injector = null): ViewRef {
|
||||||
|
|
|
@ -17,7 +17,7 @@ import {
|
||||||
|
|
||||||
import {TestBed, ViewProxy} from 'angular2/src/test_lib/test_bed';
|
import {TestBed, ViewProxy} from 'angular2/src/test_lib/test_bed';
|
||||||
import {Injector} from 'angular2/di';
|
import {Injector} from 'angular2/di';
|
||||||
import {Component, View} from 'angular2/annotations';
|
import {Component, View, onDestroy} from 'angular2/annotations';
|
||||||
import * as viewAnn from 'angular2/src/core/annotations_impl/view';
|
import * as viewAnn from 'angular2/src/core/annotations_impl/view';
|
||||||
import {DynamicComponentLoader} from 'angular2/src/core/compiler/dynamic_component_loader';
|
import {DynamicComponentLoader} from 'angular2/src/core/compiler/dynamic_component_loader';
|
||||||
import {ElementRef} from 'angular2/src/core/compiler/element_ref';
|
import {ElementRef} from 'angular2/src/core/compiler/element_ref';
|
||||||
|
@ -68,6 +68,28 @@ export function main() {
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it('should allow destroying dynamically-loaded components',
|
||||||
|
inject([TestBed, AsyncTestCompleter], (tb, async) => {
|
||||||
|
tb.overrideView(MyComp, new viewAnn.View({
|
||||||
|
template: '<dynamic-comp #dynamic></dynamic-comp>',
|
||||||
|
directives: [DynamicComp]
|
||||||
|
}));
|
||||||
|
|
||||||
|
tb.createView(MyComp).then((view) => {
|
||||||
|
var dynamicComponent = view.rawView.locals.get("dynamic");
|
||||||
|
dynamicComponent.done.then((ref) => {
|
||||||
|
view.detectChanges();
|
||||||
|
expect(view.rootNodes).toHaveText("hello");
|
||||||
|
|
||||||
|
ref.dispose();
|
||||||
|
|
||||||
|
expect(ref.instance.destroyed).toBe(true);
|
||||||
|
expect(view.rootNodes).toHaveText("");
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
it('should allow to destroy and create them via viewcontainer directives',
|
it('should allow to destroy and create them via viewcontainer directives',
|
||||||
ijTestBed((tb: TestBed, async) => {
|
ijTestBed((tb: TestBed, async) => {
|
||||||
tb.overrideView(MyComp, new viewAnn.View({
|
tb.overrideView(MyComp, new viewAnn.View({
|
||||||
|
@ -287,16 +309,23 @@ class DynamicComp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({selector: 'hello-cmp', appInjector: [DynamicallyCreatedComponentService]})
|
@Component({
|
||||||
|
selector: 'hello-cmp',
|
||||||
|
appInjector: [DynamicallyCreatedComponentService],
|
||||||
|
lifecycle: [onDestroy]
|
||||||
|
})
|
||||||
@View({template: "{{greeting}}"})
|
@View({template: "{{greeting}}"})
|
||||||
class DynamicallyCreatedCmp {
|
class DynamicallyCreatedCmp {
|
||||||
greeting: string;
|
greeting: string;
|
||||||
dynamicallyCreatedComponentService: DynamicallyCreatedComponentService;
|
dynamicallyCreatedComponentService: DynamicallyCreatedComponentService;
|
||||||
|
destroyed: boolean = false;
|
||||||
|
|
||||||
constructor(a: DynamicallyCreatedComponentService) {
|
constructor(a: DynamicallyCreatedComponentService) {
|
||||||
this.greeting = "hello";
|
this.greeting = "hello";
|
||||||
this.dynamicallyCreatedComponentService = a;
|
this.dynamicallyCreatedComponentService = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDestroy() { this.destroyed = true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({selector: 'dummy'})
|
@Component({selector: 'dummy'})
|
||||||
|
|
Loading…
Reference in New Issue