navigate and navigateByUrl not working correctly in ngOnInit on 2.0.0-rc.1

22,391

Solution 1

UPDATE

So, I downloaded your code to see what the issue is.

  1. the Router documentation suggests to use navigate() instead of navigateByUrl(). So you might want to change that.
  2. It seems that the root route is overriding your subroute.

To resolve the issue, you simply need to put the current root route into a separate subroute, eg. /home.

{ path: '/home', component: HomeComponent }

I could not find any documentation for this behavior, but for a reason similar to this, even the Angular tutorial at angular.io does not have a root route. It only has /dashboard, /heroes and /detail/:id.


PREVIOUS ANSWER

Looks like you are missing the ROUTER_PROVIDER in the @Component declaration. Try adding that as:

@Component({
  selector: 'my-app',
  templateUrl: './app/app.component.html',
  directives: [ROUTER_DIRECTIVES],
  providers: [ROUTER_PROVIDERS]
})

Also, import the appropriate references:

import {Routes, Router, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from '@angular/router';

Solution 2

Probably you should do that trick setTimeout(() => this._router.navigate(["/letter"]), 0);

Solution 3

Try moving it into routerOnActivate instead of ngOnInit. You can do it by importing OnActivate and implementing it in your class.

Also make sure you are bootstraping your app with ROUTER_PROVIDERS.

Solution 4

I'm pretty sure it's a bug. I opened a new issue on github: https://github.com/angular/angular/issues/8733

When I get an answer / it's fixed I'll update this answer here with the solution (if there is any).

In the meantime there is a workaround, see @funkycoder post. Even though the workaround is for most users probably also not satifying.

Solution 5

I don't know if that's a bug or you are doing anything wrong. But instead of using the timeout method, I would suggest following approach:

ngOnInit() {
    this.redirectToPath();
}

redirectToPath() {
    this._router.navigate(["/letter"]);
}


Share:
22,391
OschtärEi
Author by

OschtärEi

Updated on July 23, 2022

Comments

  • OschtärEi
    OschtärEi almost 2 years

    Since the 2.0.0-rc.1 router.navigate or router.navigateByUrl doesn't seem to be working anymore correctly when used inside ngOnInit.

    I don't get an error or anything, but it looks like the navigate happens too early, because right after it the HomeComponent is loaded and "replaces" the content of the LetterComponent. However the URL is correct (/letter).

    If I put the navigate in a setTimeout with 1000ms it works again.

    Do I need to use a different lifecycle event or am I doing something wrong? Or is it a bug?

    Note that: normally the value which specifies where to navigate to, comes from a cookie (is dynamic).

    Here's my simplified app component:

    @Component({
      selector: 'my-app',
      templateUrl: './app/app.component.html',
      directives: [ROUTER_DIRECTIVES]
    })
    @Routes([
      { path: '/', component: HomeComponent },
      { path: '/letter',component: LetterComponent },
      { path: '/cv', component: CVComponent },
      { path: '/attachment', component: AttachmentComponent }
    ])
    export class AppComponent implements OnInit {
    
      constructor(private _router: Router) {
      }
    
      ngOnInit() {
          // todo: currently not working correctly (issue?)
          //also doesn't work: this._router.navigateByUrl("/letter");
          this._router.navigate(["/letter"]);
      }
    }
    

    Here's a demo of what happens. When I access the app without a path it should directly navigate to the /letter "page" - as you can see the URL changes, but the content is the wrong one (the content is the one of the home component).


    Update:

    Here are my imports, if they are of any relevance:

    import {Component} from '@angular/core';
    import {Router, Routes, ROUTER_DIRECTIVES} from '@angular/router';
    import {OnInit} from '@angular/core';
    

    Here's my bootstraping:

    import { bootstrap }  from '@angular/platform-browser-dynamic';
    import {AppComponent} from './app.component';
    import {ROUTER_PROVIDERS} from '@angular/router';
    import 'rxjs/Rx';
    
    bootstrap(AppComponent, [
      ROUTER_PROVIDERS
    ]);
    

    Regarding @eburgers post:

    Here's what I did:

    import {Component} from '@angular/core';
    import {Routes, ROUTER_DIRECTIVES, Router, ROUTER_PROVIDERS, OnActivate} from '@angular/router';
    import {OnInit} from '@angular/core';
    
    @Component({
      selector: 'my-app',
      templateUrl: './app/app.component.html',
      directives: [ROUTER_DIRECTIVES]
    })
    @Routes([
      { path: '/', component: HomeComponent },
      { path: '/letter',component: LetterComponent },
      { path: '/cv', component: CVComponent },
      { path: '/attachment', component: AttachmentComponent }
    ])
    export class AppComponent implements OnActivate {
    
      constructor(private _router: Router) {
      }
    
      routerOnActivate() {
          // todo: currently not working correctly (issue?)
          //also doesn't work: this._router.navigateByUrl("/letter");
          this._router.navigate(["/letter"]);
      }
    }