andreivictor
andreivictor

Reputation: 8511

Angular CDK - Injecting the Custom overlay container class into a component creates new instance of it

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:

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

https://stackblitz.com/edit/angular-wksbmf-9xdxcv

Upvotes: 1

Views: 3486

Answers (1)

Apoorva Chikara
Apoorva Chikara

Reputation: 8783

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.

Upvotes: 1

Related Questions