10

There is some fundamental concept of routing in Angular 4 that I don't understand.

index.html:

<base href="/">

File structure:

- app
|- app.routings.ts
|- collections
|-- collection.component.ts
|-- collection.component.html
|-- collectioninfo.component.ts
|-- collectioninfo.component.html
|- shared
|-- header.component.html
|-- header.component.ts

I have a link in my header.component.html:

<a class="nav-link" [routerLink]="['/collections']">
    Collections
</a>

If I click it I land on localhost:4200/collections. When a button is clicked, the url is programmatically changed (in collection.component.ts):

this.router.navigate(['/collections/', collection.name]);

I end up on localhost:4200/collections/name - all fine. Now I programatically want to get back to /collections (in collectioninfo.component.ts):

this.router.navigate(['/collections']);

But that doesn't work. The url doesn't change and I get an error that says a parameter couldn't be loaded - so apparently /collections/name is being loaded again. Thought it might is a path issue, but things like this also don't work:

this.router.navigate(['../collections']);

Additional info: When I manually reload the page while being on /collections I'm being forwarded to the home page again, but I think that is another issue and not related to this behaviour.

app.routing.ts:

const APP_ROUTES: Routes = [
  ...
  { path: 'collections', component: CollectionComponent },
  { path: 'collections/:id', component: CollectionInfo },
];
Derek Brown
  • 4,232
  • 4
  • 27
  • 44
user3255061
  • 1,757
  • 1
  • 30
  • 50
  • have you tried `navigateByUrl` instead of `navigate`, I don't know if it will fix your issue, but I use that for my programmatic page changes – Surreal Sep 13 '17 at 15:09
  • 1
    Thanks for the hint, unfortunately that doesn't work either (some behaviour). – user3255061 Sep 13 '17 at 15:16
  • how is your empty path defined and what is isAuthenticated in your header? – JayDeeEss Sep 13 '17 at 15:28
  • Flip the order of your routes, making the most specific route first. The reason you're getting the error regarding the missing parameter is because `/collections` is falling through to the `CollectionsInfo` route. Alternatively, use an exact match for the route. – Brandon Taylor Sep 13 '17 at 15:30
  • maybe it is syntaxual? Try without the brackets `this.router.navigateByUrl('/collections');` – Surreal Sep 13 '17 at 15:30
  • @Brandon: Flipping the order doesn't work - I put { path: 'collections/:id', component: CollectionInfo } to the very top, but without success. How would I use an exact match of the route? You mean the path in the link? – user3255061 Sep 13 '17 at 19:55
  • @JayDeeEss: Sorry about "isAuthenticated" - forgot to put that out. This part of the menu is hidden for non-authenticated users. Put it out now. The empty path (if that's would you mean, sorry, I'm not so familiar with Angular 2 yet) is { path: '', component: HomeComponent, pathMatch: 'full' }. – user3255061 Sep 13 '17 at 19:56
  • 1
    @Surreal: It just works without the brackets anyway. But thanks for the hint. – user3255061 Sep 13 '17 at 19:57
  • @user3255061 try: `pathMatch: 'full'` – Brandon Taylor Sep 13 '17 at 19:58
  • @Brandon: No, unfortunately that doesn't work. – user3255061 Sep 14 '17 at 18:18
  • There are some posts suggesting that the current page might gets reloaded because of clicking a button that lacks "type='button'" (https://stackoverflow.com/questions/39001709/page-reloading-on-child-routing?rq=1), but I get the same behaviour after adding the type. – user3255061 Sep 15 '17 at 09:01
  • Can you provide a reproducable plunkr? I have a similar setup but no issues and can't really spot an error here. (using `navigate` the first part is always relative to the base if you use it like `navigate(['/collections'])`, so nothing wrong with that. Guess your components don't try to redirect onInit or something like that? – malifa Sep 15 '17 at 09:15
  • @lexith: Thanks for the suggestion, will do. Before I do so can you please just elaborate what you mean with "components don't try to redirect onInit"? Why should my components redirect somewhere? – user3255061 Sep 15 '17 at 09:56
  • I just wanted to ask if there could be some other components / services that mess with your routes. well i guess you dont have a `router.navigate` in your ngOnInit but maybe you have a Guard somewhere that intervenes with your routing? I dont know, that's why i wanted to see more of your code :) – malifa Sep 15 '17 at 10:03
  • @lexit Thanks a lot for helping me out. I found the issue, posted it as answer below. – user3255061 Sep 18 '17 at 00:16

2 Answers2

6

Turns out my firebase code is messed up - it tries to reload the page before going to another route. That caused an error, because some parameters that handed over from the previous route were missing.

export const routing = RouterModule.forRoot(APP_ROUTES, { enableTracing: true })

in app.routing.ts was very useful for debugging.

user3255061
  • 1,757
  • 1
  • 30
  • 50
5

In your relative path this.router.navigate(['../collections']); you are trying to navigate to localhost:4200/collections/collections. Try this.router.navigate(['../']);

If this doesn't work, also supply the ActivatedRoute as a relativeTo parameter:

constructor(route: ActivatedRoute, router: Router) {}

navigate() {
  this.router.navigate(['../'], { relativeTo: this.route });
}

relativeTo works by creating a path relative to whatever entry you provide, and it does not necessarily need to be the current route.

Juan Stiza
  • 523
  • 2
  • 15
tylerwgrass
  • 656
  • 4
  • 19
  • this.router.navigate(['../']) doesn't throw an error, but it leads me to my homepage. this.router.navigate(['../collections']) doesn't work though, it throws the same error as stated above. I then tried ActivatedRoute: Imported it (import { ActivatedRoute } from '@angular/router';) and put it in the constructor, but "relativeTo: route" throws a syntax error: Cannot find name "route" any. Although it's properly written in the constructor: route: ActivatedRoute. Do you have a hunch why it's behaving like that? – user3255061 Sep 13 '17 at 19:51
  • Try changing `route` to `this.route`. I make this mistake more often than I'd like to admit. – tylerwgrass Sep 13 '17 at 20:01
  • This could be pretty embarrassing, but I have no clue what I'm doing wrong syntax wise. Must be a small thing, but I don't see it. As it's not related to the original issue I thought it's better to post this on pastebin: https://pastebin.com/CY3M2Gvk. Can you spot any obvious error there? – user3255061 Sep 14 '17 at 18:18
  • I don't see anything wrong with what you have there, and using this.router.navigate(['/collections']); should have worked fine as well. Maybe there is something else.. But I don't see anything wrong with what you have. I'm sorry I couldn't help any more :( – tylerwgrass Sep 15 '17 at 04:17
  • I missed "public" in the constructor. But still relativeTo doesn't solve the problem. Thanks for your help though. – user3255061 Sep 15 '17 at 08:51