Is it somehow possible in Angular2 to get notified BEFORE the component is already destroyed!? i.e. When it is ABOUT TO be destroyed.
I have a container component which holds a ViewContainerRef on one of its children which will be used to dynamically load views. If the container component itself gets destroyed (in my case due to a *ngFor directive in the parent component), i want to detach the view which is currently loaded in the ViewContainerRef and attach it on another container again.
Thing is: In the ngOnDestroy() life cycle hook the ViewContainerRef is already cleared, so all views are destroyed, nothing to detach anymore.
My solution for now (not really a workaround) is to implement the ngOnChanges() of the parent component which uses the ngFor directive. If the array which is iterated by ngFor has changed and its length is shorter than before i simply detach the views of all containers (@ViewChildren containers: QueryList) and map them to the containers (Map). I then re-insert the mapped views again by iterating the new containers list and loading the ViewRefs from the map, in the containers.changed listener.
@Component({
selector: 'container-collection',
directives: [Container],
template: `<container *ngFor="let i of views"></container>`
})
export class ContainerCollection {
public views = [];
@ViewChildren(Container) private containers: QueryList<Container>;
private viewMap = new Map<Container, ViewRef>();
public ngOnChanges(changes: {[key: string]: SimpleChange]}): void {
if(changes['views']) {
//detach all views and remember which container had which view
this.viewMap = new Map<Container, ViewRef>();
this.containers.forEach(container => {
var view = container.viewContainer.detach();
if(view)
this.viewMap.set(container, view);
});
}
}
public ngAfterViewInit(): void {
//insert the views again (into the appropriate containers)
this.containers.changes.subscribe( () => {
this.containers.forEach(container => {
var view = this.viewMap.get(container);
if(view)
container.viewContainer.insert(view);
});
});
}
}
@Component({
selector: 'container',
template: `<div #viewContainer></div>`
})
export class Container {
@ViewChild('viewContainer') public viewContainer;
}
The code is just a draft and may contain syntax errors. But the idea (which is working for me) should be clear.
It would be great of the Angular2 team to add a LifeCycle hook which gets called BEFORE a component gets actually destroyed. (e.g. ngBeforeDestroy() ) or so.