I am trying to add and remove components dynamically depending on the the screen size using ComponentFactoryResolver.
@ViewChild('sidebarContainer', { read: ViewContainerRef }) sidebarContainer: ViewContainerRef;
_handleBodyResize() {
let self = this;
if (typeof ResizeObserver == 'undefined') return;
const obs = new ResizeObserver(entries => {
let entry = entries[0];
if ((entry.contentRect.width) < MOBILE_WIDTH) {
if (this.deviceType !== DeviceType.mobile) {
this.removeSidebar();
this.deviceType = DeviceType.mobile;
}
} else {
if (this.deviceType !== DeviceType.desktop) {
this.addSidebar();
this.deviceType = DeviceType.desktop;
}
};
});
removeSidebar() {
this.sidebarContainer.clear();
this.sidebarRef.destroy();
}
addSidebar() {
this.sidebarContainer.clear();
//_cfr is componentFactoryResolver
const compFactory = this._cfr.resolveComponentFactory(this.array[0]);
let comp = this.sidebarContainer.createComponent(compFactory);
this.sidebarRef = comp;
}
and the HTML
<div class="sidebar-container">
<div #sidebarContainer>
</div>
This sidebarContainer viewContainerRef can't seem to hold on to the references and creates new instance of the SidebarComponent whenever the with of the body goes from < 768px
to >= 768px
and doesn't delete the previously created component saved in sidebarRef and event the sidebarContainer.clear() method doesn't work
Strangely if I use window.addEventListener('resize'...
it works.
Is there some underlying ResizeObserver technicality that I am not aware of and is there a way to make it work with ResizeObserver
Update
I forgot to mention this, but the code inside the resize observer executes on time and calls both of the functions appropriately.
The else section always creates a new instance of the SidebarComponent and renders it into view but this.sidebarContainer.clear()
and this.sidebarRef.destroy
don't remove the previously created instances even though while debugging, I can see that sidebarContainer
and sidebarRef
are not undefined and are relevant instances of ViewContainerRef and ComponentRef respectively.
Angular performs change detection in response to various triggers. DOM events, ajax requests, and timers/observables will trigger Angular's change detection.
The window's resize
event is an example of a DOM event that will trigger change detection.
As far as I know, Angular's change detection is not automatically triggered by ResizeObserver
. So you'll need to explicitly tell Angular to detect changes using ChangeDetectorRef.detectChanges()
:
constructor(private changeDetector: ChangeDetectorRef) {}
ngAfterViewInit() {
const obs = new ResizeObserver(entries => {
// Perform updates in response to resize
// Then tell Angular to detect changes
this.changeDetector.detectChanges();
});
obs.observe(this.resizeDiv.nativeElement);
}
Here's a StackBlitz example.
If you only care about changes to the viewport dimensions, there's no need to use ResizeObserver
. The window resize
event will work fine in all browsers.