David Gabrichidze
David Gabrichidze

Reputation: 635

Component does not have route configuration - nested routes angular2 RC1

I have nested routes.

@Routes([
{ path: "/", component: RootComponent },
{ path: "/parent", component: ParentComponent }])

Second level route has parameters.

@Routes([
{ path: "/:id", component: ChildComponent },
{ path: "/child/:id", component: ChildComponent }]) //same component

When I navigate with RouterLink:

['/parent/child/1']

I'm getting error:

Component 'ChildComponent' does not have route configuration.

If I change nested route to one level (flat) route:

@Routes([
{ path: "/", component: RootComponent },
{ path: "/parent", component: ParentComponent },
{ path: "/child/:id", component: ChildComponent }])

than everything works normally (RouterLink is same).

Question: Where is my mistake?

Update: Nested route also do not works when I use just a simple url: e.g. http://server/parent/child/1 url

Upvotes: 3

Views: 2488

Answers (3)

Morteza Manavi
Morteza Manavi

Reputation: 33216

Problem:

The reason for this error message is that with new Angular 2 RC1 routing, you are essentially building a route tree so when you ask for '/parent/child/1' your second last route segment (/child/) sends you into ChildComponent and angular looks into ChildComponent to see if there are any routes that it can match to the next segment being (/1) and since you do not have any routes defined in ChildComponent it throws this exception:

Cannot match any routes. Current segment: '1'. Available routes: [].


Solution:

Defining your (flat) route tree in the AppComponent like you did is definitely one way to deal with this issue. The other way is to differentiate your second level routes by changing your routes in ParentComponent to:

@Routes([
    { path: 'childs', component: ChildComponent },    
    { path: 'child/:id', component: ChildComponent },            
])

Basically we are creating two branches being childs and child/:id both routed to ChildComponent.

Why defining a childs route works?

Basically Angular 2 RC1 router does not treat child/:id route as a whole when a route named child is also defined, instead, angular router breaks child/:id route into two route segments of child and :id and then use the definition for the child route to take you to the ChildComponent and then look for a route definition for the :id segment in ChildComponent which it couldn't find any. By renaming child route to childs we are forcing angular to take child/:id as a whole and take us to ChildComponent as the final destination which is what we want.


Deep Links

As for your second issue with deep links:

Nested route also do not works when I use just a simple url: e.g. http://server/parent/child/1

Assuming that you are using the default PathLocationStrategy as your LocationStrategy, you need to make sure your web server serves the index.html file for each route path. For example, in live server I add the following argument to the web server startup command:

live-server --entry-file=index.html

Update: Looks like this is a known bug in RC1 and changing the order of the Routes makes everything to work correctly. Please see David's answer for an example.

Upvotes: 4

David Gabrichidze
David Gabrichidze

Reputation: 635

OMG, I have just switched order of second level route and it worked:

@Routes([
{ path: "/child/:id", component: ChildComponent },
{ path: "/:id", component: ChildComponent }]) //same component

It works, but do not know why.

I'm sure these are url mappings:

  • http://localhost/parent/1 -> selects second config
  • http://localhost/parent/child/1 -> selects first config

Update

As it showed up, it is known issue for now: https://github.com/angular/angular/issues/8420

Upvotes: 3

anthony moss
anthony moss

Reputation: 31

When you define your route, you can define that the route isn't terminated by adding this syntax "/...".

For your parent route, you should write it like that :

Component for parent:

import {TestComponent} from '';
@Routes([
    { path: "/", component: RootComponent },
    { path: "/parent/...", name: 'Parent', component: TestComponent }
])

Component for children called TestComponent:

@Routes([
    {path: '/:id', name: 'Id', component: ChildComponent },
    {path: '/child/:id', name: 'ChildId', component: ChildComponent }
])

Upvotes: 0

Related Questions