Che*_*dar 2 subscribe observable angular-material angular candeactivate
我已经使用角度表单验证实现了 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;
}
}
Run Code Online (Sandbox Code Playgroud)
组件保护
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在这是我的确认弹出代码。我的问题是如果我使用默认的 confirm() 方法(下面代码中的注释行),它会弹出窗口,并要求是或否,这很完美。但是如果我在这里使用自定义材质弹出窗口,我必须订阅 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;
}
}
Run Code Online (Sandbox Code Playgroud)
从模态中我返回“OK”,如下所示
constructor(private dialogRef: MatDialogRef<ConfirmationComponent>) { }
btnOk() {
this.dialogRef.close('OK');
Run Code Online (Sandbox Code Playgroud)
}
任何帮助表示赞赏。
编辑 :
我在我的组件中扩展了 formdeactivate
export class EditFormComponent extends FormCanDeactivate implements OnInit {
@ViewChild('form', { static: true }) form: NgForm;
constructor(){super();}
}
Run Code Online (Sandbox Code Playgroud)
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;
}
}
Run Code Online (Sandbox Code Playgroud)
如果要将其应用于组件,只需扩展FormCanDeactivate该类。
您可以使用 AngularCanDeactivate路由保护来实现它。
export class CanDeactivateGuard implements CanDeactivate<ComponentCanDeactivate> {
canDeactivate(component: ComponentCanDeactivate): boolean {
return component.canDeactivate();
}
}
Run Code Online (Sandbox Code Playgroud)
您将其添加到路由中的相关路由中。我假设您了解所有这些是如何工作的,因为您提供了它的代码和演示。
如果您只是想在组件具有脏表单时阻止路由停用,那么您已经解决了问题。
您现在希望在用户离开脏表单之前给他们一个选择。您使用同步 javascript 实现了这一点confirm,但您想使用异步的 Angular Material 对话框。
首先,由于您将异步使用它,您需要从您的守卫返回一个异步类型。您可以返回 aPromise或Observable。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)
);
}
Run Code Online (Sandbox Code Playgroud)
YesNoComponent您创建的自定义对话框组件在哪里作为对话框的包装器。
export class YesNoComponent {
constructor(private dialogRef: MatDialogRef<YesNoComponent> ) { }
Ok(){
this.dialogRef.close(true);
}
No(){
this.dialogRef.close(false);
}
}
Run Code Online (Sandbox Code Playgroud)
演示:https : //stackblitz.com/edit/angular-custom-popup-candeactivate-mp1ndw
| 归档时间: |
|
| 查看次数: |
1517 次 |
| 最近记录: |