3

Is it possible to configure a "terminal" route with children, or in other words, a route with "optional" children.

I'm trying to create a routable master/detail view, where the details are not displayed initially, and the list is not destroyed when the details view is opened.

For example, navigate to /a, and then, without destroying a, navigate to /a/1.

First attempt:

const routes: RouterConfig = [
  //...
  { path: 'a', component: AListComponent, children: [
    { path: ':id', component: ADetailsComponent }
  ]},
  //...
];

... with this configuration, the following error is thrown:

EXCEPTION: Error: Uncaught (in promise): Error: Cannot match any routes: 'a'

Second attempt:

const routes: RouterConfig = [
  //...
  { path: 'a', component: AListComponent },
  { path: 'a', component: AListComponent, children: [
    { path: ':id', component: ADetailsComponent }
  ]},
  //...
];

... the list component is destroyed and recreated, i.e. if it has user inputs, the values are gone.

Third attempt - create an "Empty" component and load it by default.

const routes: RouterConfig = [
  //...
  { path: 'a', component: AListComponent, children: [
    { path: '', component: EmptyComponent },
    { path: ':id', component: ADetailsComponent }
  ]},
  //...
];

... works, but feels like a workaround.

Is there a better way?

Ronald Zarīts
  • 11,819
  • 8
  • 39
  • 42
  • What about using a dummy component that doesn't display anything for the "optional" route? AFAIK what you're looking for is not supported. – Günter Zöchbauer Aug 01 '16 at 05:37
  • 1
    @GünterZöchbauer, thanks for the comment. Your suggestion is basically my third attempt - it works, but doesn't "feel right". However, if you make your comment an answer, I'd be happy to accept it. How does the approach look to you? Tour of heroes (https://angular.io/docs/ts/latest/tutorial/toh-pt2.html) uses an *ngIf to achieve this, but using the router feels a bit better. If the empty component approach doesn't look completely terrible, this could be a way forward, at least for the time being. – Ronald Zarīts Aug 01 '16 at 08:01
  • IMHO if `ngIf` is a good fit mostly depends on whether you want to reflect the state in the URL. If this isn't necessary or useful than `ngIf` should be fine. – Günter Zöchbauer Aug 01 '16 at 08:04
  • Yeah, the state should be reflected in the URL in my case. I want users to be able to navigate directly to `/a/1`, instead of opening `a/` and selecting `1`. – Ronald Zarīts Aug 01 '16 at 08:37

2 Answers2

3

An even simpler version of your 3rd attempt is to simply use an empty path with nothing else in it, not even a component:

const routes: Routes = [
  { path: 'a', component: AListComponent, children: [
    { path: '' },
    { path: ':id', component: ADetailsComponent }
  ]},
];

Victor Savkin has written about componentless routes, although he doesn't go so far as to use a completely empty route like this (his examples contain either a redirect or a children property).

Depending on your setup, you can even take it a step further and remove the /a path. I have a routes declaration like this in a feature module, lazy-loaded under path: 'module-path':

const routes: Routes = [
  { path: '', component: AListComponent, children: [
    { path: '' },
    { path: ':id', component: ADetailsComponent }
  ]},
];

So routing to /module-path loads AListComponent which contains an empty <router-outlet>, and routing to /module-path/5 populates the outlet with ADetailsComponent.

nickspoon
  • 1,347
  • 12
  • 18
1

An empty dummy component that doesn't show anything like shown in your 3rd attempt is the best way in my opinion.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567