我的网址为http://www.localhost:4200/profile
和http://www.localhost:4200/editProfile
。这两个URL都提供给登录用户。现在我只希望通过可用的导航菜单访问/editProfile
,而不是直接在地址栏上写入URL并按Enter键。如果用户这样做,他将被重定向到/profile
路径。
类似于允许在/editProfile
上发布但没有GET的内容。
可以使用路线模块提供的CanActivate来实现吗?
由于
答案 0 :(得分:5)
萨米特。我问你的目的是因为我解决这个问题的方法不是阻止用户通过地址栏导航。这样做会破坏应该拥有该页面合法访问权限的用户。如果用户已经登录,为什么不允许她直接访问edit profile
页面?当用户试图在她的浏览器中使用前进和后退导航按钮时,它也会破坏事物,并且会让我感到非常沮丧。
如果你还想这样做......
您可以在路线定义中使用CanActivate
path: 'editProfile',
component: EditProfileComponent,
canActivate:[EditProfileGuard]
EditProfileGuard
是一种只有在标志设置为true时才允许导航的服务
@Injectable()
export class EditProfileGuard implements CanActivate {
//must be set to true for navigation to succeed
allow = false;
canActivate(){
if(this.allow){
this.allow = false;
return true;
}
else return false;
}
}
如果用户通过浏览器地址栏导航,则会因“{1}}为假而拒绝访问”。
当用户点击导航菜单中的链接时,请将allow
设置为true,然后再将其发送到新路线
allow
请务必将此服务添加到import {EditProfileGuard} from '...'
import {Router} from '@angular/router';
...
export class MyComponent{
constructor(private guard:EditProfileGuard, private router:Router){}
//execute this when link is clicked
goToProfile(){
//so navigation will be allowed
this.guard.allow = true;
this.router.navigateByUrl('editProfile');
}
}
的{{1}}数组中。
回应您的评论:
我会为摘要页面创建一个providers
必需参数,因此路由定义为AppModule
结帐页面的链接(或用户保存的网址)将具有{{} 1}},摘要组件可以使用checkoutID
来检索和显示详细信息。
如果未签出的用户尝试直接导航到摘要页面,则/summary/:id
将丢失,导航将失败。
在摘要组件的id
中,我会验证id
,这样如果用户发明假id
并尝试导航,我可以重定向而不是加载组件
这将允许合法用户直接导航,以及前进/后退导航工作。
答案 1 :(得分:0)
很棒的答案@BeetleJuice。实际上,您可以利用外部路由事件将重新实例化您的应用程序,从而清除所有变量(Angular Routing Gotchas)。
更进一步,您可以创建第二个服务来抽象出“内部”路由:
的内部router.service.ts 强> 的
import { Injectable } from '@angular/core';
import { Router, NavigationExtras, UrlTree } from '@angular/router';
@Injectable()
export class InternalRouter {
private _isNavigationAllowed = false;
get isNavigationAllowed(): boolean {
return this._isNavigationAllowed;
}
constructor(private router: Router) { }
navigate(commands: any[], extras?: NavigationExtras): Promise<boolean> {
return this.runNavigation(() => this.router.navigate(commands, extras));
}
navigateByUrl(url: string | UrlTree): Promise<boolean> {
return this.runNavigation(() => this.router.navigateByUrl(url));
}
private runNavigation(navigation: () => Promise<boolean>): Promise<boolean> {
this._isNavigationAllowed = true;
return navigation()
.then(success => {
this._isNavigationAllowed = false;
return Promise.resolve(success);
})
.catch(e => {
this._isNavigationAllowed = false;
return Promise.reject(e);
});
}
}
的内部only.guard.ts 强> 的
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { InternalRouter } from './internal-router.service';
@Injectable()
export class InternalOnlyGuard implements CanActivate {
constructor(private router: Router, private internalRouter: InternalRouter) { }
canActivate(): boolean {
if (!this.internalRouter.isNavigationAllowed) {
this.router.navigateByUrl('/'); // Or other logic
return false;
}
return true;
}
}
注意事项:
runNavigation()
采取了冷的承诺,因此在它准备好之前它不会开始路由。我发现这种方法很好,因为InternalRouter
完全负责自己的状态。