ОБНОВЛЕНИЕ:
Я провел рефакторинг на основе ответа @Blind Despair ниже. Теперь он использует модуль Overlay из Angular CDK. Вот код для Guard:
@Injectable({
providedIn: 'root',
})
export class PendingChangesGuard
implements CanDeactivate<ComponentCanDeactivate> {
content = 'A simple string content modal overlay';
constructor(private overlayService: OverlayService) {}
canDeactivate(
component: ComponentCanDeactivate
): boolean | Observable<boolean> {
return component.canDeactivate()
? true
: this.openConfirmDialog(this.content);
}
openConfirmDialog(content: TemplateRef<any> | ComponentType<any> |
string) {
const ref = this.overlayService.open(this.content, null);
return ref.afterClosed$.subscribe((res) => {});
}
}
Проблема в том, что эта строка возвращает подписку, и мой охранник должен возвращать либо логическое значение, либо Observable:
return ref.afterClosed$.subscribe((res) => {});
Вот OverlayService class:
@Injectable({
providedIn: 'root',
})
export class OverlayService {
constructor(private overlay: Overlay, private injector: Injector) {}
open<R = any, T = any>(
content: string | TemplateRef<any> | Type<any>,
data: T
): RaOverlayRef<R> {
const configs = new OverlayConfig({
hasBackdrop: true,
panelClass: ['modal', 'is-active'],
backdropClass: 'modal-background',
});
const overlayRef = this.overlay.create(configs);
const myOverlayRef = new RaOverlayRef<R, T>(overlayRef, content,
data);
const injector = this.createInjector(myOverlayRef, this.injector);
overlayRef.attach(new ComponentPortal(OverlayComponent, null,
injector));
return myOverlayRef;
}
createInjector(ref: RaOverlayRef, inj: Injector) {
const injectorTokens = new WeakMap([[RaOverlayRef, ref]]);
return new PortalInjector(inj, injectorTokens);
}
}
А вот RaOverlay class:
export interface OverlayCloseEvent<R> {
type: 'backdropClick' | 'close';
data: R;
}
// R = Response Data Type, T = Data passed to Modal Type
export class RaOverlayRef<R = any, T = any> {
afterClosed$ = new Subject<OverlayCloseEvent<R>>();
constructor(
public overlay: OverlayRef,
public content: string | TemplateRef<any> | Type<any>,
public data: T // pass data to modal i.e. FormData
) {
overlay.backdropClick().subscribe(() =>
this._close('backdropClick', null));
}
close(data?: R) {
this._close('close', data);
}
private _close(type: 'backdropClick' | 'close', data: R) {
this.overlay.dispose();
this.afterClosed$.next({
type,
data,
});
this.afterClosed$.complete();
}
}
Любые советы по рефакторингу openConfirmDialog ( ) вернуть то, что мне нужно?