更新:
以下の@BlindDespairの回答に基づいてリファクタリングしました。現在、AngularCDKのオーバーレイモジュールを使用しています。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クラスは次のとおりです。
@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クラスです。
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()をリファクタリングして必要なものを返す方法に関するヒントはありますか?
モーダルを開くだけでは結果を定義できないため、そのガードでブール値を返すことはできません。ユーザー入力を待つcanDeactivate
必要があります。つまり、ガードはまたはを返すPromise
必要がありObservable
ます。残念ながら、現在のモーダルダイアログは単純すぎて、そのユースケースをサポートできません。基本的には、次のような.afterClosed()
ものがPromise<boolean>
必要です。またはObservable<boolean>
、ユーザーが[はい/いいえ]をクリックしたときに、プロミスを解決するか、サブジェクトに値を出力して完了します。そうすれば.afterClosed()
、ガードからの結果を簡単に返すことができます。ただし、そのためにサービスとモーダルをリファクタリングする必要があります。もちろん、あなたは持つことができますafterClosed()
モーダルコンポーネントのメソッドとしてですが、そのすべてのメソッドをガードやそれを使用DialogRef
するものに公開したくないので、公開したいものだけを公開するを導入することをお勧めします。しかし、これがすでに解決されているのに、なぜ車輪の再発明をするのでしょうか。@angular/cdk
非常にスマートなモーダルダイアログを少ない労力で作成するために使用できる、と呼ばれる驚くべき角度モジュールがあります。この記事を確認できます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加