Search code examples
angulartypescriptroutesangular-routing

Angular routing keeps previous component displayed and doesn't fully load the next one


I have a component which is a dinamically generated angular table that has to be displayed at 'table' path. But first, the app launches on the 'auth' page, which is my login page. If the authentification is correct, I get redirected to /table no problem, but: 1) auth component is still displayed 2) the table is not loaded, ngOnInit() isn't called, it seems like none of the ts code is loaded, just the basic html.

If I disable canActivate(), it doesn't change anything, but if i put a routerLink to /table in the auth component, everything works fine...

This may have something to do with the way I authenticate (GoogleAuth), so, here's some of the code, even though I'm not sure it could be useful..

auth.component.ts

import { Component, OnInit, ViewChild, ElementRef} from '@angular/core';
import { AuthService } from '../../services/auth.service';
import { Router } from '@angular/router';


@Component({
  selector: 'app-auth',
  templateUrl: './auth.component.html',
  styleUrls: ['./auth.component.scss']
})
export class AuthComponent implements OnInit {

  constructor(private authService: AuthService, private router: Router){}

 auth2: any;

 
  @ViewChild('loginRef', {static: true }) loginElement: ElementRef;


  ngOnInit() {
 
    this.googleSDK();
 
  }
 
  prepareLoginButton() {
  
    this.auth2.attachClickHandler(this.loginElement.nativeElement, {},
      (googleUser) => {
        
        //ici, l'utilisateur est authentifié
      
        let profile = googleUser.getBasicProfile();

        console.log('Token || ' + googleUser.getAuthResponse().id_token);
        console.log('ID: ' + profile.getId());
        console.log('Name: ' + profile.getName());
        console.log('Image URL: ' + profile.getImageUrl());
        console.log('Email: ' + profile.getEmail());
        // YOUR CODE HERE

        this.authService.isAuth = true;
        this.router.navigate(['/table']);
              
 
      }, (error) => {
        alert(JSON.stringify(error, undefined, 2));
      });
  }
  googleSDK() {
 
    window['googleSDKLoaded'] = () => {
      window['gapi'].load('auth2', () => {
        this.auth2 = window['gapi'].auth2.init({
          client_id: '88179289847-pcj5c8u563k4igvqof1k65tcbqu4q97f.apps.googleusercontent.com',
          cookie_policy: 'single_host_origin',
          scope: 'profile email'
        });
        this.prepareLoginButton();
      });
    }
    console.log("google sdk");
    (function(d, s, id){
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) {return;}
      js = d.createElement(s); js.id = id;
      js.src = "https://apis.google.com/js/platform.js?onload=googleSDKLoaded";
      fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'google-jssdk'));
 
  }
}

auth.guard.ts

import { Injectable, OnInit } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService} from '../services/auth.service';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {

  ngOnInit(){
  }

  constructor (private authService: AuthService, private router: Router){}

  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
      if(this.authService.isAuth){
        return true;
      } 
      else{
        this.router.navigate(['/auth']);
    }
    return true;
  }
  
}


Solution

  • You are stepping outside of the NgZone. The callback of this.auth2.attachClickHandler is no longer in the zone, so there is no more change detection while routing. You should update your code to re-enter the zone using ngZone.run():

    constructor(
      private authService: AuthService,
      private router: Router,
      private ngZone: NgZone
    ){}
    
    this.auth2.attachClickHandler(this.loginElement.nativeElement, {}, (googleUser) => {
      this.ngZone.run(() => {
        // ...
        this.router.navigate(['/table']);
      }); 
    });