Rusty Rob
Rusty Rob

Reputation: 17213

how to close material overlay from within componentPortal instance

I had to pass the overlayRef manually, is there a nicer way to include it in the components constructor with DI?

service code:

display() {
    const overlayRef = this.overlay.create({
      positionStrategy: this.overlay.position().global().top(),
    });
    const portal = new ComponentPortal(ErrorsListBottomSheetComponent);
    this.ref = overlayRef.attach<ErrorsListBottomSheetComponent>(portal);
    this.ref.instance.overlayRef = overlayRef;
    overlayRef.backdropClick().subscribe(() => {
      overlayRef.detach();
    });

  }

component code:

export class ErrorsListBottomSheetComponent implements OnInit {
  overlayRef: OverlayRef; -- REMOVE THIS--

  constructor(
-- ADD SOMETHING HERE --
  ) {}

close() {
    if (this.overlayRef) {
      this.overlayRef.detach();
    }
  }

better yet, is there something for overlay similar to

<button mat-dialog-close>close</button>

instead of

<button (click)="close()">close</button>

Upvotes: 6

Views: 12744

Answers (3)

ibrcic
ibrcic

Reputation: 856

Yes, there is a nicer way of doing this by providing the injector in the ComponentPortal constructor and then just injecting the OverlayRef in the component directly.

const injector = Injector.create({
  providers: [{ provide: COMPONENT_OVERLAY_REF, useValue: overlayRef }],
});
const userProfilePortal = new ComponentPortal(FooComponent, undefined, injector);

After injector is defined and passed to ComponentPortal we can just inject OverlayRef normally in FooComponent:

constructor(@Inject(COMPONENT_OVERLAY_REF) private overlayRef: OverlayRef) {}

Injection token is defined like so:

export const COMPONENT_OVERLAY_REF = new InjectionToken('COMPONENT_OVERLAY_REF');

You could even provide the OverlayRef directly without using custom MOBILE_MENU_OVERLAY_REF InjectionToken, but I would advise against that as it could lead to some problems and confusion when component is used directly, without CDK overlay.

Upvotes: 4

Pranit More
Pranit More

Reputation: 516

You can use @Ouput event emitter to emit event from component and then subscribing it in service.

Component Code:

export class ErrorsListBottomSheetComponent implements OnInit {
  @Output() closePanel = new EventEmitter<void>();

  ...

  close() {
    this.closePanel.emit();
  }
}

Service code:

display() {
   ...
   this.ref = overlayRef.attach<ErrorsListBottomSheetComponent>(portal);
   this.ref.instance.closePanel.subscribe(() => overlayRef.detach());
}

Html Code:

<button (click)="close()">Close</button>

Upvotes: 12

Amith p
Amith p

Reputation: 9

Try like this

constructor(private _bottomSheetRef: MatBottomSheetRef<?>, private _bottomSheet: MatBottomSheet) {
}

close() {
  this._bottomSheet.dismiss()
}

// Here MatBottomSheetRef<?> ? is your component

Upvotes: 1

Related Questions