实施 CanDeactivate Guard 时出错
Error while implementing CanDeactivate Guard
我目前正在尝试对我的 angular 应用程序实施 CanDeactivate Guard,该应用程序已经有 HTTP 拦截器来解析以进行身份验证。
但是添加 CanDeactivate 守卫会抛出错误,如下所述。
我已经在 AppModule 的 providers 数组中注册了实现 CanDeactivate 接口的 Class。
我在路由的canDeactivate属性中注册了实现CanDeactivate接口的class
class 实施 CanDeactivate 接口:
export interface CanComponentDeactivate {
canComponentDeactivate(): boolean;
}
@Injectable({providedIn: 'root'})
export class AppRegisterDeactivateGuard implements CanDeactivate<AppRegisterComponent> {
canDeactivate(
component: AppRegisterComponent,
currentRoute: ActivatedRouteSnapshot,
currentState: RouterStateSnapshot
): Observable<boolean>|Promise<boolean>|boolean {
return component.isDeactivated;
}
}
应用停用防护的组件:
@Component({
selector: 'app-app-register',
templateUrl: './app-register.component.html',
styleUrls: ['./app-register.component.css']
})
export class AppRegisterComponent implements OnInit, CanComponentDeactivate {
isDeactivated = false;
@ViewChild('registrationForm') registForm: NgForm;
.
.
canComponentDeactivate() {
if (this.registForm.dirty) {
this.isDeactivated = confirm('You have modified changes in the form. \nDo you still want to navigate away ? ');
}
return this.isDeactivated;
}
}
该端点的路由定义:
...
{ path: 'register', component: AppRegisterComponent, canDeactivate: ['AppRegisterDeactivateGuard'] },
模块中的提供程序数组:
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: AppAuthInterceptService,
multi: true
}, AppRegisterDeactivateGuard],
bootstrap: [AppComponent]
错误
StaticInjectorError(Platform: core)[AppRegisterDeactivateGuard]:
NullInjectorError: No provider for AppRegisterDeactivateGuard!
Error: StaticInjectorError(AppModule)[AppRegisterDeactivateGuard]:
StaticInjectorError(Platform: core)[AppRegisterDeactivateGuard]:
NullInjectorError: No provider for AppRegisterDeactivateGuard!
at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get (core.js:8896)
at resolveToken (core.js:9141)
at tryResolveToken (core.js:9085)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:8982)
at resolveToken (core.js:9141)
at tryResolveToken (core.js:9085)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:8982)
at resolveNgModuleDep (core.js:21218)
at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get (core.js:21907)
at getToken (router.js:2865)
at resolvePromise (zone.js:831)
at resolvePromise (zone.js:788)
at zone.js:892
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
at Object.onInvokeTask (core.js:17290)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
at drainMicroTaskQueue (zone.js:601)
at ZoneTask.push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (zone.js:502)
at invokeTask (zone.js:1744)
您需要在泛型中传递接口:
export class AppRegisterDeactivateGuard implements CanDeactivate<CanComponentDeactivate > {
然后实现canDeactivate方法
TLDR;
将您的路线更改为:
{ path: 'register', component: AppRegisterComponent, canDeactivate: [AppRegisterDeactivateGuard] }
将您的提供商更改为:
[{
provide: HTTP_INTERCEPTORS,
useClass: AppAuthInterceptService,
multi: true
}]
更长的答案:
AppRegisterDeactivateGuard 同时具有 {providedIn: 'root'}
并在模块中将其声明为提供程序是不必要的。 See the Angular provider docs.
这里的问题是路由和提供商的组合。
现在您的路线正在通过字符串名称寻找令牌,但是可以通过 class 名称获得。
使用 @Injectable({providedIn: 'root'})
你如何使用 class 名称作为令牌,它将作为 AppRegisterDeactivateGuard 提供。
在你的供应商中AppRegisterDeactivateGuard
你如何拥有它也将使其作为AppRegisterDeactivateGuard可用。
我不推荐这样做,但如果你想或需要通过字符串名称引用它,你可以像这样把它放在提供程序中:
{ provide: 'AppRegisterDeactivateGuard', useClass: AppRegisterDeactivateGuard }
我目前正在尝试对我的 angular 应用程序实施 CanDeactivate Guard,该应用程序已经有 HTTP 拦截器来解析以进行身份验证。 但是添加 CanDeactivate 守卫会抛出错误,如下所述。
我已经在 AppModule 的 providers 数组中注册了实现 CanDeactivate 接口的 Class。 我在路由的canDeactivate属性中注册了实现CanDeactivate接口的class
class 实施 CanDeactivate 接口:
export interface CanComponentDeactivate {
canComponentDeactivate(): boolean;
}
@Injectable({providedIn: 'root'})
export class AppRegisterDeactivateGuard implements CanDeactivate<AppRegisterComponent> {
canDeactivate(
component: AppRegisterComponent,
currentRoute: ActivatedRouteSnapshot,
currentState: RouterStateSnapshot
): Observable<boolean>|Promise<boolean>|boolean {
return component.isDeactivated;
}
}
应用停用防护的组件:
@Component({
selector: 'app-app-register',
templateUrl: './app-register.component.html',
styleUrls: ['./app-register.component.css']
})
export class AppRegisterComponent implements OnInit, CanComponentDeactivate {
isDeactivated = false;
@ViewChild('registrationForm') registForm: NgForm;
.
.
canComponentDeactivate() {
if (this.registForm.dirty) {
this.isDeactivated = confirm('You have modified changes in the form. \nDo you still want to navigate away ? ');
}
return this.isDeactivated;
}
}
该端点的路由定义:
...
{ path: 'register', component: AppRegisterComponent, canDeactivate: ['AppRegisterDeactivateGuard'] },
模块中的提供程序数组:
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: AppAuthInterceptService,
multi: true
}, AppRegisterDeactivateGuard],
bootstrap: [AppComponent]
错误
StaticInjectorError(Platform: core)[AppRegisterDeactivateGuard]:
NullInjectorError: No provider for AppRegisterDeactivateGuard!
Error: StaticInjectorError(AppModule)[AppRegisterDeactivateGuard]:
StaticInjectorError(Platform: core)[AppRegisterDeactivateGuard]:
NullInjectorError: No provider for AppRegisterDeactivateGuard!
at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get (core.js:8896)
at resolveToken (core.js:9141)
at tryResolveToken (core.js:9085)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:8982)
at resolveToken (core.js:9141)
at tryResolveToken (core.js:9085)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:8982)
at resolveNgModuleDep (core.js:21218)
at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get (core.js:21907)
at getToken (router.js:2865)
at resolvePromise (zone.js:831)
at resolvePromise (zone.js:788)
at zone.js:892
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
at Object.onInvokeTask (core.js:17290)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
at drainMicroTaskQueue (zone.js:601)
at ZoneTask.push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (zone.js:502)
at invokeTask (zone.js:1744)
您需要在泛型中传递接口:
export class AppRegisterDeactivateGuard implements CanDeactivate<CanComponentDeactivate > {
然后实现canDeactivate方法
TLDR; 将您的路线更改为:
{ path: 'register', component: AppRegisterComponent, canDeactivate: [AppRegisterDeactivateGuard] }
将您的提供商更改为:
[{
provide: HTTP_INTERCEPTORS,
useClass: AppAuthInterceptService,
multi: true
}]
更长的答案:
AppRegisterDeactivateGuard 同时具有 {providedIn: 'root'}
并在模块中将其声明为提供程序是不必要的。 See the Angular provider docs.
这里的问题是路由和提供商的组合。
现在您的路线正在通过字符串名称寻找令牌,但是可以通过 class 名称获得。
使用 @Injectable({providedIn: 'root'})
你如何使用 class 名称作为令牌,它将作为 AppRegisterDeactivateGuard 提供。
在你的供应商中AppRegisterDeactivateGuard
你如何拥有它也将使其作为AppRegisterDeactivateGuard可用。
我不推荐这样做,但如果你想或需要通过字符串名称引用它,你可以像这样把它放在提供程序中:
{ provide: 'AppRegisterDeactivateGuard', useClass: AppRegisterDeactivateGuard }