Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 router.navigate() not working first time

I have the following routes defined:

export const routes: Routes = [
    { path: '', component: HomeComponent, pathMatch: 'full', canActivate: [AuthGuardService] },
    { path: 'sites', component: SiteIndexComponent, resolve: { siteSummaries: SiteSummariesResolve }, canActivate: [AuthGuardService] },
    { path: 'qa-tasks', component: QaTaskIndexComponent, resolve: { investigations: InvestigationsResolve, reviews: ReviewsResolve }, canActivate: [AuthGuardService] },
    { path: 'error', component: ErrorComponent },
    { path: '**', redirectTo: '' }
];

Users of my app see totally different pages based on their role including their "landing" (home) page. I'm using my HomeComponent to route the user to the correct landing page based on role like this:

export class HomeComponent implements OnInit {

    private roles: any;

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

    ngOnInit() {
        var currentUser = this.authService.getCurrentUser();
        this.roles = currentUser.roles;
        this.redirect();
    }

    private redirect() {
        var route;
        if (this.inRole('site-user-role')) {
            route = 'sites';
        }
        else if (this.inRole('qa-user-role')) {
            route = 'qa-tasks';
        }
        if (route) {
            this.router.navigate([route]);
        }
        else {
            this.router.navigate(['error']);
        }
    }

    private inRole(role) {
        return _.includes(this.roles, role);
    }
}

When the HomeComponent is first loaded after login, the route does not navigate to, for example, the 'sites' route, but strangely it resolves the siteSummaries dependency. After the first time it fails to redirect, I can navigate to another route and then try to navigate to the '' route and it correctly redirects to the 'sites' route.

Why is the initial navigation not working? Based on other similar questions about navigate() not working, I've tried changing my route to '/sites' and './sites', but to no avail.

Update It looks like it has to do with resolving a dependency for a route. If redirect to the 'error' route in my redirect() function, it does it successfully the first time. If I add a resolve to my 'error' route, it fails to navigate to it the first time. The odd thing is it makes the HTTP call to fulfill the dependency. Is this an issue with it not awaiting the return of navigate()'s promise?

Update 2 Here are the requested classes:

export class SiteIndexComponent implements OnInit {

    public siteSummaries: any;
    public totalRegisteredCount: number;
    public totalscreenFailedCount: number;
    public totalinProgressCount: number;

    constructor(private route: ActivatedRoute) { }

    ngOnInit() {
        this.siteSummaries = this.route.snapshot.data['siteSummaries'];
        this.totalRegisteredCount = this.getTotal('registeredCount');
        this.totalscreenFailedCount = this.getTotal('screenFailedCount');
        this.totalinProgressCount = this.getTotal('inProgressCount');
    }

    private getTotal(prop): number {
        var total = 0;
        _.forEach(this.siteSummaries, function (summary) {
            return total += summary[prop];
        });
        return total;
    }
}

@Injectable()
export class SiteSummariesResolve implements Resolve<any> {

    constructor(private sitesService: SitesService) { }

    resolve(route: ActivatedRouteSnapshot) {
        return this.sitesService.getSiteSummaries();
    }
}

getCurrentUser(): any {
    var currentUser = sessionStorage.getItem('currentUser');
    if (!currentUser) {
        return null;
    }
    return JSON.parse(currentUser);
}

Update 3 I threw this into my app.component:

private navigationInterceptor(event: RouterEvent): void {
    if (event instanceof NavigationStart) {
        console.log('started: ' + JSON.stringify(event));
    }
    if (event instanceof NavigationEnd) {
        console.log('ended: ' + JSON.stringify(event));
    }
    if (event instanceof NavigationCancel) {
        console.log('cancelled:' + JSON.stringify(event));
    }
    if (event instanceof NavigationError) {
        console.log('error:' + JSON.stringify(event));
    }
}

On the times when it fails to load the route (the first time), there is first an event instance of NavigationStart and then an instance of NavigationCancel. Here is what event looks like on the NavigationCancel: {"id":2,"url":"/sites","reason":""}. As you can see, no reason is given...

like image 317
im1dermike Avatar asked Apr 20 '17 13:04

im1dermike


1 Answers

I still don't know why it was cancelling my route navigation, but a work around I've come up with is to change ngInit to the following:

ngOnInit() {
    var currentUser = this.authService.getCurrentUser();
    this.roles = currentUser.roles;
    var that = this;
    setTimeout(function () { that.redirect(); }, 50);
}

Wrapping my redirect call in a timeout allows things to work as expected with the exception of a imperceptible delay. It would seem it's some sort of timing issue? If I try setting the timeout to 20 it also doesn't work.

like image 65
im1dermike Avatar answered Oct 02 '22 21:10

im1dermike