The redirectTo
failed to redirect to a link with canActivate
when I logged in .
The redirectTo
works fine when I logged out, it redirectTo my /login
component and redirectTo
to /index
after logged in.
But it stick on ''
when I'm logged In.
I had add console.log
to my authGuard
, and the redirect url "/index" did go in that function at the stick to ''
situation with no crash in development tool.
But after comment the canActivate
, the redirectTo
work fine like before.
By the way, my authGuard with canActivate
work fine in other situations(exclude redirecTo
)
Here's my app-routing.module.ts
/* import... */
const appRoutes: Routes = [
{ path: 'login', component: LoginComponent },
{ path: '', redirectTo : '/index', pathMatch: 'full' },
{ path: '**', component: PageNotFoundComponent }
];
/* ngmodel and export ... */
and here's my index-routing.module.ts
/* import ... */
const indexRoutes: Routes = [
{
path: 'index',
component: IndexComponent,
canActivate: [AuthGuard], //<- if comment this will work
},
];
/* ngmodel and export ... */
here's my auth-guard.module.ts
/* import ... */
@Injectable()
export class AuthGuard implements CanActivate {
constructor(
private authService: AuthService,
private router: Router
) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
let url: string = state.url;
//redirectTo did get in here
console.log(url); //<-- this show /index
return this.checkLogin(url);
}
checkLogin(url: string): boolean {
if (this.authService.login_data && (this.authService.login_data.userprofile || !this.authService.login_data.need_login)) {
return true;
}
this.authService.get_login_data()
.subscribe(
data => {
this.authService.login_data = data;
if (data.userprofile || !data.need_login) {
return true;
}
this.authService.redirectUrl = url;
this.router.navigate(['/login']);
return false;
},
error => { this.authService.errMsg = <any>error;}
);
}
}
By the way I had updated my project to angular4.0.1
Thanks.
UPDATE:
I've changed my guard return from boolean to Observable
but it still doesn't work.
here's the code I had used.
checkLogin(url: string): Observable<boolean> {
if (this.authService.login_data && (this.authService.login_data.userprofile || !this.authService.login_data.need_login)) {
console.log('gonna return observable true');
return Observable.of(true);
//return true;
}
this.authService.get_login_data()
.subscribe(
data => {
this.authService.login_data = data;
if (data.userprofile || !data.need_login) {
console.log('in subscribe and gonna return observable true');
return Observable.of(true);
//return true;
}
this.authService.redirectUrl = url;
this.router.navigate(['/login']);
return Observable.of(false);
//return false;
},
error => { this.authService.errMsg = <any>error;}
);
}
In my console, I got in subscribe and gonna return observable true
UPDATE:
after check after checking this
AuthGuard doesn't wait for authentication to finish before checking user
the problem may be that canActivate
doesn't wait the subscribe end.
In you checkLogin()
of AuthGuard
:
checkLogin(url: string): boolean {
if (this.authService.login_data && (this.authService.login_data.userprofile || !this.authService.login_data.need_login)) {
return true;
}
this.authService.get_login_data()
.subscribe(
data => {
this.authService.login_data = data;
if (data.userprofile || !data.need_login) {
return true;
}
this.authService.redirectUrl = url;
this.router.navigate(['/login']);
return false;
},
error => { this.authService.errMsg = <any>error;}
);
}
it's return type is boolean, it return true, in some condition, it is ok. But, the later part has some problem. You didn't return anything, until you subscribe the result and return based on that result.
It means, this function will return undefined, so the canActivate check will not work.
[Updated] You want to set user data from the result, you should use do()
in your authService.get_login_data()
to set it. When you subscribe the result, this 'do' function will be called. And in your checkLogin()
use .map()
instead of subscribe()
to map the login result data to boolean.
In this situation, you should return a Observable type, like:
checkLogin(url: string): Observable<boolean> {
if (this.authService.login_data && (this.authService.login_data.userprofile || !this.authService.login_data.need_login)) {
return Observable.of(true); // wrap true in Observable
}
return this.authService.get_login_data()
.map(
data => {
if (data.userprofile || !data.need_login) {
return true;
}
this.authService.redirectUrl = url;
this.router.navigate(['/login']);
return false;
},
error => { this.authService.errMsg = <any>error;}
);
}
I've solved my problem by changing subscribe to map.
Angular2 canActivate() calling async function
here's my code after edited.
checkLogin(url: string): Observable<boolean>|boolean {
if (this.authService.login_data && (this.authService.login_data.userprofile || !this.authService.login_data.need_login)) {
console.log('gonna return observable true');
return Observable.of(true);
}
return this.authService.get_login_data()
.map(
data => {
this.authService.login_data = data;
if (data.userprofile || !data.need_login) {
console.log('in subscribe and gonna return observable true');
//return Observable.of(true);
return true;
}
this.authService.redirectUrl = url;
this.router.navigate(['/login']);
//return Observable.of(false);
return false;
},
error => { this.authService.errMsg = <any>error;}
);
}
in the map i got error if i return Observable(true)
Type 'Observable<Observable<boolean>>' is not assignable to type 'boolean | Observable<boolean>'.
Thanks for help and suggestions.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.