Requirement
Use a custom OverlayContainer
class in order to open Angular Material Snackbars
on a specific DOM element (not on body
).
At this point, I know that:
OverlayContainer
class is a singletonbody
.The code I've tried
I provided the custom class in the providers array.
providers: [
{provide: OverlayContainer, useClass: AppOverlayContainer}
]
And the class is:
export class AppOverlayContainer extends OverlayContainer {
/**
* Append the OverlayContainer to the custom element
*/
public appendToCustomContainer(element: HTMLElement): void {
// this._containerElement is 'cdk-overlay-container'
element.appendChild(this._containerElement);
}
**
* Remove the OverlayContainer from the custom element and append it to body
*/
public removeFromCustomContainer(): void {
this._document.body.appendChild(this._containerElement);
}
}
In my component, before opening a snackbar, I will call:
AppOverlayContainer.appendToCustomContainer(HTMLElement)
And after the snackbar closes, I will call:
AppOverlayContainer.removeFromCustomContainer();
The issue:
When injecting the AppOverlayContainer
into the component constructor, it will create a new instance of this class and also of the OverlayContainer
:
constructor(
private _snackBar: MatSnackBar,
private _appOverlayContainer: AppOverlayContainer
) {}
It works only if I inject the OverlayContainer
, then use it like:
constructor(
private _snackBar: MatSnackBar,
private _appOverlayContainer: OverlayContainer
) {}
(this._appOverlayContainer as AppOverlayContainer).appendToCustomContainer(appOverlayWrapperContainer);
(this._appOverlayContainer as AppOverlayContainer).removeFromCustomContainer();
Which seems kind of tricky.
I really don't understand what I am missing here.
Stackblitz
You should use useExisting
to avoid this problem having two instances of your services. The reason is some components are asking for OverlayContainer
and some are asking for AppOverlayContainer
and angular created instances for each. Updating the useClass
to useExisting
will help to let angular only use one instance:
providers: [
{provide: OverlayContainer, useExisting: AppOverlayContainer}
]
You can check here for the details, it will be helpful to understand different properties while using services.