OschtärEi
OschtärEi

Reputation: 2255

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

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"]);
  }
}

Upvotes: 8

Views: 32910

Answers (7)

nativelectronic
nativelectronic

Reputation: 862

in other cases , probably you have a href="#" in the tag, wich is overriding after router.navigate

Upvotes: 0

Dan Obregon
Dan Obregon

Reputation: 1091

You have probably already resolved this by now, but I wonder if the order of your routes is the real problem. If I remember correctly, the router tries to match the path to the one given. So, in your listing, '/letter' matches the route '/' first, so it returns 'HomeComponent'.

I think if you had reordered your routes so that the route '/' was last, then it would have matched '/letter' correctly.

Upvotes: 1

Parth Savaliya
Parth Savaliya

Reputation: 361

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"]);
}


Upvotes: 0

OschtärEi
OschtärEi

Reputation: 2255

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.

Upvotes: 2

amritashan
amritashan

Reputation: 583

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';

Upvotes: 6

Eran Shabi
Eran Shabi

Reputation: 14979

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.

Upvotes: 2

Roman
Roman

Reputation: 79

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

Upvotes: 6

Related Questions