我在Angular应用程序上使用Guard来解析初始关键数据.在Angular的第4版中,我喜欢这样:
// app.routing.ts
routing = [{
path: '', component: AppComponent, canActivate: [ResolveGuard],
}];
// resolve.guard.ts
@Injectable()
export class ResolveGuard implements CanActivate {
constructor(
private _api: ApiService,
) { }
canActivate(): any {
return this._api.apiGet('my/url').map(response) => {
if ( response.status === 'success') {
// Consume data here
return true;
}
return false;
}).first();
}
}
Run Code Online (Sandbox Code Playgroud)
由于Angular 5上的新版本的Http不再使用该.map()属性,因此无效.
如果我.map()改为.subscribe()它不会抛出任何错误,但应用程序永远不会正确解决.另一方面,使用.first()和/或.map()抛出一些错误,正如此版本所预期的那样.
在这种情况下我该怎么办?
我只需要在加载初始数据时激活该路由.
编辑以添加有关该apiGet功能的信息:
constructor(private _http: HttpClient) {} …Run Code Online (Sandbox Code Playgroud) rxjs angular angular-router-guards angular-router angular-httpclient
我有这个AuthGuard:
export class AuthGuard implements CanActivate {
constructor (private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
if (localStorage.getItem('token')) {
return true;
}
this.router.navigate(['/login']);
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
我在我的提供AppModule:
@NgModule({
declarations: [/*...*/],
imports: [NotificationRoutingModule],
providers: [AuthService, AuthGuard],
bootstrap: [AppComponent]
})
export class AppModule {
}
Run Code Online (Sandbox Code Playgroud)
我试图在我的路由模块中使用这个后卫,如下所示:
const routes = [
{
path: 'notification',
component: NotificationRootComponent
children: [
{path: '', redirectTo: 'list', pathMatch: 'full'},
{path: 'list', component: NotificationListComponent, canActivate: [AuthGuard]},
{path: ':id', …Run Code Online (Sandbox Code Playgroud) 如果我的 Angular 应用程序,如果我导航(通过明确输入 URL 或单击指向它的页面链接)到http://localhost:4200/#/sign-in页面加载正常并显示我的登录表单。如果我然后Refresh在浏览器中单击,我将被带回根页面http://localhost:4200/#/。
我的路由器很简单:
export const routes: Route[] = [
{ path: 'sign-up', component: SignUpComponent},
{ path: 'sign-in', component: SignInComponent},
{ path: 'admin', loadChildren: 'app/admin/admin.module#AdminModule'},
{ path: 'dashboard', loadChildren: 'app/user/user.module#UserModule', canActivate: [ UserLoggedInGuard ]},
{ path: '', pathMatch: 'full', component: HomeComponent},
{ path: '**', pathMatch: 'full', component: PageNotFoundComponent},
]
Run Code Online (Sandbox Code Playgroud)
我在用
@angular/core": "^4.2.4@angular/router": "^4.2.4任何想法为什么会发生这种情况?
angular-routing angular angular-router-guards angular-router
据我所知,它的调用签名是canActivate这样的:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
}
Run Code Online (Sandbox Code Playgroud)
我有一个服务,它需要一个组件的名称并返回访问该组件所需的用户角色,以便我可以检查canActivate我的守卫功能,活动用户是否具有相应的角色。我的问题是,我不知道如何访问该组件。经过一番谷歌搜索后,我找到了这样的解决方案:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const nameOfComponent = route.routeConfig.component.name;
return doSomeRoleCheck(nameOfComponent);
}
Run Code Online (Sandbox Code Playgroud)
但就我而言,我只是收到一个错误:“无法读取未定义的属性‘名称’”。如何访问活动路由的组件,尤其是作为字符串的名称?
我发现,我确实在父路线上检查了这个守卫。当我在子路由中检查它时,它可以工作。如何从父组件访问子组件ActivatedRouteSnapshot
typescript angular-routing angular angular-router-guards angular-router
我有一个带有输入字段的Angular 6组件。如果任何输入字段在用户试图离开时验证失败,则会触发该canDeactivate功能的守卫。守卫是通用的,因为这一逻辑需要发生在应用程序中的多个组件上。它运行起来很漂亮,但是当我尝试对这种行为进行单元测试时,canDeactivate从未达到过守卫中的功能。达到了守卫本身,但从未达到过功能。我是否以不正确的方式提供警卫?
防护组件接口
export interface GuardComponent {
canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}
Run Code Online (Sandbox Code Playgroud)
CanDeactivateGuard
export class CanDeactivateGuard implements CanDeactivate<GuardComponent> {
constructor() { }
canDeactivate(component: GuardComponent): Observable<boolean> | Promise<boolean> | boolean {
return component.canDeactivate();
}
}
Run Code Online (Sandbox Code Playgroud)
成分
export class MyComponent implements OnInit, GuardComponent {
...
canDeactivate() {
if (!this.form.invalid) {
return true;
}
this.isError = true;
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
规格
const routes = [
{
path: 'my-component',
component: MyComponent,
canDeactivate: [CanDeactivateGuard], …Run Code Online (Sandbox Code Playgroud) javascript unit-testing jasmine angular-router-guards angular6
如果我的解析防护失败,我想显示 404 页面/组件,但我不希望浏览器的 URL 发生更改。
我可以在不更改解析中的 URL 的情况下进行导航,如下所述:
this.router.navigate(['/404'], { skipLocationChange: true })
Run Code Online (Sandbox Code Playgroud)
当从应用程序内访问此防护时,此功能有效。但是,如果我直接导航到该页面,例如:/posts/1234路由器将 URL 更改为后备路由(认为 404 组件已正确显示)。如果我不跳过位置更改,一切都会按预期工作,但我的网址中有“/404”,这是我不想要的。
目前有没有办法用路由器实现这一点,或者这是一个错误?
我目前有一个主页,可以路由到我公司运行的所有不同工作流程.我们有大约15个不同的工作流程,每个工作流程都由用户角色保护.如果您在数据库中没有正确的用户角色,则不会看到该页面的相应链接.我们保护服务器端点,但我担心的是向人们显示链接或不显示链接的最佳方式是什么,我宁愿不重复代码.
这是一种方法:
我有一个像这样的html页面
<ul>
<li *ngIf="authService.hasRequiredRole('users.user-admin')" routerLink="/user">Users</li>
<li *ngIf="authService.hasRequiredRole('users.role-admin')" routerLink="/role">Roles</li>
</ul>
Run Code Online (Sandbox Code Playgroud)
我有这样的身份验证服务:
hasRequiredRole(roles: string | [string]) {
if (typeof roles === 'string') {
roles = [roles];
}
for (const roleSlug of roles) {
if (this.user.roles.find((role: any) => {
return role.slug === roleSlug;
})) {
return true;
}
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
我有一个像这样的路由的路由器:
const routes: Routes = [{
path: 'user',
data: {
allowedRoles: 'users.user-admin'
},
loadChildren: 'app/user/user.module#UserModule',
canActivate: [AuthGuard]
},
{ path: 'home', component: HomeComponent }]
Run Code Online (Sandbox Code Playgroud)
AuthGuard只检查用户是否已登录,然后使用路由中的数据来检查用户是否具有正确的角色.
如您所见,我们使用字符串'users.user-admin'有两个不同的位置.
我想我们应该有一个带两个警卫的路由器.一名警卫将检查用户是否已登录,另一名警卫将检查用户是否具有正确的角色.该角色将在此处进行硬编码:
export class …Run Code Online (Sandbox Code Playgroud) angular-template angular angular-router-guards angular-router
我正在尝试使用 canDeactivate 路由器防护。第一次运行代码时,我传入的组件 (ClaimsViewComponent) 为空。但是在随后的运行中,代码会按预期运行。我们试图弄清楚为什么组件在第一次运行时为空。
这是 canDeactivate 守卫代码:
@Injectable()
export class ConfirmDeactivateGuard implements
CanDeactivate<ClaimsViewComponent> {
canDeactivate(target: ClaimsViewComponent): boolean {
if (target.canDeactivate()) {
return window.confirm('Do you really want to cancel?');
}
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
这是路由模块代码:
const routes: Routes = [
{ path: ':type', component: ClaimsViewComponent, canDeactivate:
[ConfirmDeactivateGuard] }
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
Run Code Online (Sandbox Code Playgroud)
这是完整的错误堆栈:
TypeError: Cannot read property 'canDeactivate' of null
at ConfirmDeactivateGuard.canDeactivate (confirm-deactivate-guard.ts:16)
at MergeMapSubscriber.eval [as project] (router.js:3933)
at MergeMapSubscriber._tryNext (mergeMap.js:128)
at MergeMapSubscriber._next (mergeMap.js:118)
at MergeMapSubscriber.Subscriber.next (Subscriber.js:95) …Run Code Online (Sandbox Code Playgroud) 我有一个完整的角度应用程序,它使用急切加载。我想将其转换为延迟加载,但是因为我对所有路线都有保护,并且所有路线都是受保护的一条主路线的子路线,所以我不知道是否可以做到这一点并仍然使其发挥作用就像急切加载一样。
这是我在 app-routing.module 中的路由数组:
// Routing array - set routes to each html page
const appRoutes: Routes = [
{ path: 'login/:id', canActivate: [AuthGuard], children: [] },
{ path: '', canActivateChild: [AuthGuard], children: [
{ path: '', redirectTo: '/courses', pathMatch: 'full' },
{ path: 'courses', component: CourseListComponent, pathMatch: 'full'},
{ path: 'courses/:courseId', component: CourseDetailComponent, pathMatch: 'full' },
{ path: 'courses/:courseId/unit/:unitId', component: CoursePlayComponent,
children: [
{ path: '', component: CourseListComponent },
{ path: 'lesson/:lessonId', component: CourseLessonComponent, data:{ type: 'lesson'} },
{ …Run Code Online (Sandbox Code Playgroud)routes lazy-loading eager-loading angular angular-router-guards
AngularFire 身份验证防护文档显示了允许身份验证的不同方法。
仅管理员用户:
const editorOnly = pipe(customClaims, map(claims => claims.role === "editor"));
Run Code Online (Sandbox Code Playgroud)
仅限自己:
const onlyAllowSelf = (next) => map(user => !!user && next.params.userId === user.uid);
Run Code Online (Sandbox Code Playgroud)
我的问题是如何将编辑器/管理员或用户自己可以打开组件的两者结合起来。
angular ×8
typescript ×2
angular6 ×1
angularfire2 ×1
canactivate ×1
jasmine ×1
javascript ×1
lazy-loading ×1
routes ×1
rxjs ×1
unit-testing ×1