Angular2 + redirectTo not working when redirecting to link using canActivate
redirectTo
failed to redirect link from canActivate
at login.
redirectTo
works great on logout, it redirects my component /login
and redirectTo
in /index
after login.
But it clicks ''
when I am logged in.
I added console.log
to mine authGuard
, and the redirect url / index "put this function in a stick at a ''
glitch-free position in the development tool.
But after comments canActivate
, it redirectTo
works fine as before.
BTW, my authGuard s canActivate
works 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 updated my project to angular4.0.1
Thank.
UPDATE:
I changed my guard return from boolean to Observable
but it still doesn't work.
here's the code i 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 checking after checking this
AuthGuard does not wait for authentication to complete before verifying the user
the problem might be canActivate
not waiting for the end of the subscription.
source to share
In checkLogin()
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 returns boolean type, it returns true, in some state, that's ok. But, the later part has some problems. You didn't return anything until you signed the result and returned based on that result.
This means that this function will return undefined, so the canActivate check will not work.
[Updated] You want to set user data from the result, you have to use do()
in yours authService.get_login_data()
to set it. When you subscribe to the result, this "do" function will be called. And in checkLogin()
use .map()
instead subscribe()
to match the input result data to boolean.
In this situation, you must return the Observable type, for example:
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;}
);
}
source to share
I solved my problem by changing my card subscription.
Angular2 canActivate () function to call async function
here's my code after editing.
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;}
);
}
on the map i got an error if i return Observable (true)
Type 'Observable<Observable<boolean>>' is not assignable to type 'boolean | Observable<boolean>'.
Thanks for the help and suggestions.
source to share