简体   繁体   中英

Angular2+ redirectTo not working when redirect to a link with canActivate

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM