Angular 有没有办法让角路由器保护CanDeactivate在表单组件中充当保护/接口?
我读过关于使用CanDeactivate检测用户是否离开表单/路由的文章,这正是我在项目中需要的。我试着实现这个答案: 当我查看我的用户表单组件时,我将信息输入其中一个输入,然后尝试刷新,单击另一个组件,通过浏览器url导航到google.com。所有这些都不会触发该答案中的确认提示 我的项目结构设置如下:Angular 有没有办法让角路由器保护CanDeactivate在表单组件中充当保护/接口?,angular,angular-router,angular-router-guards,Angular,Angular Router,Angular Router Guards,我读过关于使用CanDeactivate检测用户是否离开表单/路由的文章,这正是我在项目中需要的。我试着实现这个答案: 当我查看我的用户表单组件时,我将信息输入其中一个输入,然后尝试刷新,单击另一个组件,通过浏览器url导航到google.com。所有这些都不会触发该答案中的确认提示 我的项目结构设置如下: > src > app - app-routing.module.ts - app.module.ts - app.component.ts - app.com
> src
> app
- app-routing.module.ts
- app.module.ts
- app.component.ts
- app.component.html
> auth
> ...
> dashboard
- dashboard.module.ts
- dashboard.component.ts
- dashboard.component.html
> components
> forms
- user-form.component.ts
- user-form.component.html
> ...
> shared
> guards
- pending-changes.guard.ts
> ...
我已经尝试过实现这个答案:
在我的仪表板模块中,我导入了pending-changes.guard,并为我的仪表板组件定义了一个路由,该组件使用我的canDeactivate:[PendingChangesGuard]
然后,我将PendingChangesGuard作为仪表板模块的NgModule中的提供者添加
在我的用户表单组件中,我从共享中的PendingChangesGuard导入ComponentCanDeactivate,然后在组件中实现ComponentCanDeactivate接口。我定义了一个名为canDeactivate()的函数,该函数检查FormGroup类型的userForm是否脏,如果脏,则返回false,这将向用户显示确认信息。如果表单没有被使用,那么我想返回true
“我的仪表板”模块中定义的路线是针对我的仪表板组件的。我的仪表板组件是我的用户表单组件的另一个组件的父级。因此,当用户通过单击其他组件来显示该组件时,包含表单html的“我的用户表单”组件没有专门设置自己的url/path/route/routerLink。我不确定这里的设置是否正确,因为我看到的大多数示例都专门为表单组件设置了一个route/path/routerLink,其中包含会触发用户提示的未保存数据
挂起的更改.guard.ts
import { CanDeactivate } from '@angular/router';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
export interface ComponentCanDeactivate {
canDeactivate: () => boolean | Observable<boolean>;
}
@Injectable()
export class PendingChangesGuard implements CanDeactivate<ComponentCanDeactivate> {
canDeactivate(component: ComponentCanDeactivate): boolean | Observable<boolean> {
// if there are no pending changes, just allow deactivation; else confirm first
return component.canDeactivate() ?
true :
// NOTE: this warning message will only be shown when navigating elsewhere within your angular app;
// when navigating away from your angular app, the browser will show a generic warning message
// see http://stackoverflow.com/a/42207299/7307355
confirm('WARNING: You have unsaved changes. Press Cancel to go back and save these changes, or OK to lose these changes.');
}
}
import { PendingChangesGuard } from '../shared/guards/pending-changes.guard';
export const routes: Routes = [
{
path: '',
component: DashboardComponent,
canDeactivate: [PendingChangesGuard]
}
];
@NgModule({
imports: [
CodemirrorModule,
CommonModule,
CronEditorModule,
FormsModule,
ReactiveFormsModule,
SimpleNotificationsModule.forRoot(),
NgbModule,
NgxsModule.forFeature(STATES),
NgxSpinnerModule,
RouterModule.forChild(routes),
SharedModule
],
declarations: COMPONENTS,
exports: COMPONENTS,
entryComponents: [ProfileComponent],
providers: [PendingChangesGuard]
})
export class DashboardModule {}
import { ComponentCanDeactivate } from '../../../../shared/guards/pending-changes.guard';
@Component({
selector: 'user-form',
templateUrl: './user-form.component.html',
styleUrls: ['./user-form.component.scss']
})
export class UserFormComponent implements OnInit, ComponentCanDeactivate {
...
userForm: FormGroup;
constructor(private fb: FormBuilder) {}
// @HostListener allows us to also guard against browser refresh, close, etc.
@HostListener('window:beforeunload')
canDeactivate(): Observable<boolean> | boolean {
// insert logic to check if there are pending changes here;
if (this.userForm.dirty === true) return false;
return true;
// returning true will navigate without confirmation
// returning false will show a confirm dialog before navigating away
}
...
}
const routes: Routes = [
{
path: 'dashboard',
canActivate: [AuthGuard],
loadChildren: './dashboard/dashboard.module#DashboardModule'
},
{
path: '',
redirectTo: '/dashboard',
pathMatch: 'full'
}
];
用户表单.component.ts
import { CanDeactivate } from '@angular/router';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
export interface ComponentCanDeactivate {
canDeactivate: () => boolean | Observable<boolean>;
}
@Injectable()
export class PendingChangesGuard implements CanDeactivate<ComponentCanDeactivate> {
canDeactivate(component: ComponentCanDeactivate): boolean | Observable<boolean> {
// if there are no pending changes, just allow deactivation; else confirm first
return component.canDeactivate() ?
true :
// NOTE: this warning message will only be shown when navigating elsewhere within your angular app;
// when navigating away from your angular app, the browser will show a generic warning message
// see http://stackoverflow.com/a/42207299/7307355
confirm('WARNING: You have unsaved changes. Press Cancel to go back and save these changes, or OK to lose these changes.');
}
}
import { PendingChangesGuard } from '../shared/guards/pending-changes.guard';
export const routes: Routes = [
{
path: '',
component: DashboardComponent,
canDeactivate: [PendingChangesGuard]
}
];
@NgModule({
imports: [
CodemirrorModule,
CommonModule,
CronEditorModule,
FormsModule,
ReactiveFormsModule,
SimpleNotificationsModule.forRoot(),
NgbModule,
NgxsModule.forFeature(STATES),
NgxSpinnerModule,
RouterModule.forChild(routes),
SharedModule
],
declarations: COMPONENTS,
exports: COMPONENTS,
entryComponents: [ProfileComponent],
providers: [PendingChangesGuard]
})
export class DashboardModule {}
import { ComponentCanDeactivate } from '../../../../shared/guards/pending-changes.guard';
@Component({
selector: 'user-form',
templateUrl: './user-form.component.html',
styleUrls: ['./user-form.component.scss']
})
export class UserFormComponent implements OnInit, ComponentCanDeactivate {
...
userForm: FormGroup;
constructor(private fb: FormBuilder) {}
// @HostListener allows us to also guard against browser refresh, close, etc.
@HostListener('window:beforeunload')
canDeactivate(): Observable<boolean> | boolean {
// insert logic to check if there are pending changes here;
if (this.userForm.dirty === true) return false;
return true;
// returning true will navigate without confirmation
// returning false will show a confirm dialog before navigating away
}
...
}
const routes: Routes = [
{
path: 'dashboard',
canActivate: [AuthGuard],
loadChildren: './dashboard/dashboard.module#DashboardModule'
},
{
path: '',
redirectTo: '/dashboard',
pathMatch: 'full'
}
];