When I create a component using ViewContainerRef
and assign instance to a property of parent component, which is responsible for child component creation, do I need to set this property to null
after I call ViewContainerRef.clear()
if I want memory to be freed?
Asked
Active
Viewed 2.5k times
9

Leonid Bor
- 2,064
- 6
- 27
- 47
2 Answers
12
No, if you assign parent component property to componentRef
angular won't remove component from memory.
Angular only destroys component and removes its own references to this component. But reference to componentRef remains to live in your component property. So i would assign null
to it. This way garbage collect will be able to clear memory
Plunker Example (add => clear => check)
@Component({
selector: 'my-app',
template: `
<div>
<button (click)="addComponent()">Add component</button>
<div #container></div>
<button (click)="clear()">Clear</button>
<button (click)="check()">check</button>
</div>
`,
})
export class App {
comp: ComponentRef<DynamicComponent>;
constructor(
private vcRef: ViewContainerRef,
private resolver: ComponentFactoryResolver) {}
addComponent() {
let factory = this.resolver.resolveComponentFactory(DynamicComponent);
this.comp = this.vcRef.createComponent(factory);
}
clear() {
this.vcRef.clear();
}
check() {
alert(this.comp);
}
}
See also

yurzui
- 205,937
- 32
- 433
- 399
-1
I am not 100% sure but Angular calls ngOnDestroy() method of dynamically created components when their parent component is removed by Router.
here is a plunker: https://plnkr.co/edit/rAX6745xZi6EvP8N78IL?p=preview
import {Component, NgModule,Injector, ComponentFactoryResolver,
TemplateRef, ViewChild, ViewContainerRef} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import {Routes, RouterModule, Route} from '@angular/router';
@Component({
selector: 'my-other',
template: `<div>other</div>`
})
export class Other {}
@Component({
selector: 'my-cmp',
template: `<div>
my cmp
<ng-content></ng-content>
</div>
`
})
export class MyComp {
ngOnDestroy() {
console.log('dynamic component ngOnDestroy is called');
}
}
@Component({
selector: 'my-app',
template: `
<a routerLink="/viewchild">go viewchild</a>
<a routerLink="/other">go other</a>
<div>
<router-outlet></router-outlet>
</div>
`
})
export class App {}
@Component({
selector: 'my-prt',
template: `
<div>
<button (click)="create()">Create</button>
<div #vc>
<my-cmp>static one</my-cmp>
</div>
</div>
`,
})
export class Parent {
@ViewChild('vc', {read: ViewContainerRef}) vc: ViewContainerRef;
cmpRef = [];
constructor(private injector: Injector, private componentFactoryResolver: ComponentFactoryResolver) {
}
create() {
const projectableNodes = [[document.createTextNode('a'), document.createTextNode('b')]];
const factory = this.componentFactoryResolver.resolveComponentFactory(MyComp);
this.cmpRef.push(this.vc.createComponent(factory, this.injector, undefined, projectableNodes);
}
ngOnDestroy() {
//this.cmpRef.forEach(ref=>ref=null);
}
}
let routes = [
{path:'viewchild', component: Parent},
{path:'other', component: Other}
];
@NgModule({
imports: [ BrowserModule, RouterModule.forRoot(routes ],
declarations: [ App, MyComp, Parent, Other ],
entryComponents: [MyComp],
bootstrap: [ App ]
})
export class AppModule {}

Julia Passynkova
- 17,256
- 6
- 33
- 32