gpt4 book ai didi

angular - 如何异步订阅用于candeactivate Guard的matdialog服务?

转载 作者:行者123 更新时间:2023-12-04 16:00:07 24 4
gpt4 key购买 nike

我已经使用 Angular 表单验证实现了 candeactivate 保护。
如果用户单击 ngForm 字段。并尝试导航到不同的选项卡,用户将获得一个自定义确认弹出窗口,其中会显示“放弃更改?”并返回 true 或 false。

这是我的守卫

import { NgForm } from "@angular/forms";
import { ComponentCanDeactivate } from './component-can-deactivate';

export abstract class FormCanDeactivate extends ComponentCanDeactivate {

abstract get form(): NgForm;

canDeactivate(): boolean {
return this.form.submitted || !this.form.dirty;
}
}

组件保护
import { HostListener } from "@angular/core";

export abstract class ComponentCanDeactivate {

abstract canDeactivate(): boolean;

@HostListener('window:beforeunload', ['$event'])
unloadNotification($event: any) {
if (!this.canDeactivate()) {
$event.returnValue = true;
}
}
}

现在这是我的确认弹出代码。我的问题是,如果我使用默认的 confirm() 方法(下面代码中的注释行),它会弹出窗口,并要求是或否,这很完美。但是如果我在这里使用自定义 Material 弹出窗口,
我必须订阅 afterclosed() 方法,该方法以异步方式执行,而我必须等到此方法执行后再继续。我怎样才能做到这一点?
import { Injectable } from '@angular/core';
import { CanDeactivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { MatMenuTrigger, MatDialog } from '@angular/material';
import { Observable } from 'rxjs/Observable';
import { ComponentCanDeactivate } from './component-can-deactivate';
import { ConfirmationComponent } from 'src/app/core/modals/confirmation/confirmation.component';


@Injectable()
export class CanDeactivateGuard implements CanDeactivate<ComponentCanDeactivate> {

constructor(private modalService: MatDialog) {

}

canDeactivate(component: ComponentCanDeactivate): boolean {

if (!component.canDeactivate()) {
// return confirm('You have unsaved changes! If you leave, your changes will be lost');

const dialogRef = this.modalService.open(ConfirmationComponent, {});
dialogRef.afterClosed().subscribe(res => {
if (res == 'OK') {
return true;
} else {
return false;
}
});
}
return true;
}
}

从模态中我返回“OK”,如下所示
constructor(private dialogRef: MatDialogRef<ConfirmationComponent>) { }

btnOk() {
this.dialogRef.close('OK');

}

任何帮助表示赞赏。

编辑 :

我在我的组件中扩展了 formdeactivate
export class EditFormComponent extends FormCanDeactivate implements OnInit {

@ViewChild('form', { static: true }) form: NgForm;

constructor(){super();}
}

Stackblitz 链接: https://angular-custom-popup-candeactivate.stackblitz.io

最佳答案

你的问题

在离开包含脏表单的组件之前,您需要一种可重用的方式来提示用户。

要求:

  • 表单是否干净没有提示
  • 如果用户想退出,导航会继续
  • 如果用户不想退出,导航将被取消

  • 您现有的解决方案

    一旦我花了一点时间来理解您的解决方案,我就会发现这是一种处理多个组件的优雅方式。

    你的设计大概是这样的:

    export abstract class ComponentCanDeactive {
    abstract canDeactivate(): boolean;
    }

    export abstract class FormCanDeactivate extends ComponentCanDeactivate {
    abstract get form(): NgForm;

    canDeactivate(): boolean {
    return this.form.submitted || !this.form.dirty;
    }
    }

    如果你想把它应用到一个组件上,你只需扩展 FormCanDeactivate类(class)。

    您可以使用 Angular CanDeactivate 来实现它路线守卫。

    export class CanDeactivateGuard implements CanDeactivate<ComponentCanDeactivate> {
    canDeactivate(component: ComponentCanDeactivate): boolean {
    return component.canDeactivate();
    }
    }


    您将其添加到路由中的相关路由中。我假设您了解所有这些是如何工作的,因为您提供了代码和演示。

    如果您只是想在组件具有脏表单时阻止路由停用,那么您已经解决了问题。

    使用对话框

    您现在希望在用户离开脏表单之前给他们一个选择。您使用同步 javascript confirm 实现了这一点,但您想使用异步的 Angular Material 对话框。

    解决方案

    首先,由于您将异步使用它,您需要从您的守卫返回一个异步类型。您可以返回 PromiseObservable . Angular Material 对话框返回 Observable ,所以我会使用它。

    现在只是设置对话框并返回可观察的关闭函数的情况。

    停用-guard.ts

    constructor(private modalService: MatDialog) {}

    canDeactivate(component: ComponentCanDeactivate): Observable<boolean> {
    // component doesn't require a dialog - return observable true
    if (component.canDeactivate()) {
    return of(true);
    }

    // set up the dialog
    const dialogRef = this.modalService.open(YesNoComponent, {
    width: '600px',
    height: '250px',
    });

    // return the observable from the dialog
    return dialogRef.afterClosed().pipe(
    // map the dialog result to a true/false indicating whether
    // the route can deactivate
    map(result => result === true)
    );
    }

    哪里 YesNoComponent是您创建的自定义对话框组件,作为对话框的包装器。

    export class YesNoComponent {

    constructor(private dialogRef: MatDialogRef<YesNoComponent> ) { }

    Ok(){
    this.dialogRef.close(true);
    }

    No(){
    this.dialogRef.close(false);
    }
    }

    演示: https://stackblitz.com/edit/angular-custom-popup-candeactivate-mp1ndw

    关于angular - 如何异步订阅用于candeactivate Guard的matdialog服务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60447241/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com