简体   繁体   中英

How can I redirect to the previous page after google login in Angular 8?

How can I redirect to the previous page after google login in Angular8?

I am saving the current URL in the localStorage and I am using it to navigate back when the user successfully login. But it is not navigating.

This is my AuthService with login function.

export class AuthService {

  constructor(private afAuth: AngularFireAuth , private route: ActivatedRoute) {}

  login() {
    let returnUrl = this.route.snapshot.queryParamMap.get('returnUrl') || '/';
    localStorage.setItem('returnUrl', returnUrl);
    this.afAuth.auth.signInWithRedirect(new firebase.auth.GoogleAuthProvider());
  }

}

This is my AuthGuardService

export class AuthGuardService implements CanActivate {
  constructor(private auth: AuthService, public router: Router) {}

  canActivate(route, state: RouterStateSnapshot) {
    return this.auth.user$.pipe(map(user => {
      if (user) { return false; }

      this.router.navigate(['/login'], { queryParams : {returnUrl : state.url}});
      return true;
    }));
  }
}

I am using app.component.ts to navigate to the previous page.

export class AppComponent {
  constructor(private auth: AuthService, router: Router) {

    auth.user$.subscribe(user => {
      if(user){
        let returnUrl = localStorage.getItem('returnUrl');
        router.navigate([returnUrl]);
      }
    });
  }

}

This is my app.module.ts where I have defined the routes.

RouterModule.forRoot([
      { path: "", component: HomeComponent },
      { path: "check-out", component: CheckOutComponent, canActivate: [AuthGuardService]  },

       //...

    ])

I am trying to access 'check-out' page from the address bar. Then it's redirecting to the login page as I want. (When the user is not login and when the user tries to access to 'check-out' page it is directing to the login page.) My URL looks like this with router parameters.

http://localhost:4200/login?returnUrl=%2Fcheck-out

But after the login, it's not redirecting back to the 'check-out' page.

After login of a user, my URI looks like this

http://localhost:4200/login?returnUrl=%2Fcheck-out

It hasn't changed. But in app.component.ts I am trying to navigate.

I can't find why this is not navigating back to the 'check-out' page after the successful login of a user.

Here is my solution after struggling with this for a full day.

Create a service for all the url operations:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class PreviousRouteService {

  public setPreviousUrl(url: string) {
    sessionStorage.setItem('previousUrl', url);
  }

  public getPreviousUrl() {
    const previousUrl = sessionStorage.getItem('previousUrl');
    return previousUrl;
  }

  public deletePreviousUrlKey() {
    sessionStorage.removeItem('previousUrl');
  }
}

Back in your guard, if they were not logged in, use state.url to get the url they were trying to go to and save it:

// save the route
this.previousRouteService.setPreviousUrl(state.url);

Use signInWithRedirect as you did before:

this.afAuth.auth.signInWithRedirect(new firebase.auth.GoogleAuthProvider());

Note that in AF 6 that extra.auth is dropped, so would look like:

this.afAuth.signInWithRedirect(new firebase.auth.GoogleAuthProvider());

After the signInWithRedirect is completed, you will be sent back to where you came from. I can't quite tell from your code, but I'm assuming that is the login page. So on that login page in the constructor put (again note I've dropped the extra.auth here for AF 6):

this.userSub = this.afAuth.authState.subscribe((user: firebase.User) => {
    this.loggedIn = !!user;
    this.user = user;
    const previousRoute = this.previousRouteService.getPreviousUrl();
    if (previousRoute) {
      this.router.navigate([previousRoute]).then(() => {
        // now reset so don't keep going back if coming to login page
        // put some time otherwise it will delete it before above is finished
        //   even though that shouldn't be the case...
        setTimeout(() => {
          this.previousRouteService.deletePreviousUrlKey();
        }, 8500);
      });
    }
  });

This isn't the most elegant solution I'm sure, but it works. I don't really know why the setTimeout is necessary either after the previous route is navigated to - what's the point of having a promise if it hasn't finished yet? Or maybe it's to do with how the authState is working and emitting, don't know but maybe a better engineer can explain. Anyways, there ya go.

FOR ANGULAR 7+

Actually since Angular 7.2 there is not need to use a service or local storage for saving the previous url. You could just use the state object to set the last url before linking to the login page. Here is an example for a login scenario.

@Component({ ... })
class SomePageComponent {
  constructor(private router: Router) {}

  checkLogin() {
    if (!this.auth.loggedIn()) {
      this.router.navigate(['login'], { state: { redirect: this.router.url } });
    }
  }
}
@Component({...})
class LoginComponent {
  constructor(private router: Router) {}

  backToPreviousPage() {
    const { redirect } = window.history.state;

    this.router.navigateByUrl(redirect || '/homepage');
  }
}
----------------

Additionally you could also pass the data in the template:

 @Component({ template: '<a routerLink="/some-route" [state]="{ redirect: router.url }">Go to some route</a>' }) class SomePageComponent { constructor(public router: Router) {} }

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