1
votes

I´m having a problem with Angular 2 router. I cannot get it to redirect to a specific child route with a named outlet. I think it´s a problem of URL encoding. I hope someone can help me. This is my routes setup:

const appRoutes: Routes = [
  { 
    path: 'browse',                
    component: BrowseComponent, 
    children: [
      { 
        path: 'first', 
        component: BrowseFirstComponent,
        outlet: 'view'
      },
      { 
        path: 'second', 
        component: BrowseSecondComponent,
        outlet: 'view'
      },
      { 
        path: 'third', 
        component: BrowseThirdComponent, 
        outlet: 'view'
      },
    ] 
  },
  { path: 'search', component: SearchComponent },
  { path: '',       redirectTo: '/browse/(view:first)', pathMatch: 'full' },
];

If I navigate to http://mysrv/browse/(view:first) manually (per typing in the url), it works fine. But if I naviagte to http://mysrv/ instead the router tries to redirect me to 'browse/(view%3Afirst)' which does not work:

EXCEPTION: Uncaught (in promise): Error: Cannot match any routes: 'browse/(view%3Afirst)'

I´m using Angular 2.0.0 and router Package 3.0.0

Can somebody help me please?

2

2 Answers

2
votes

You need to update to a more recent Angular2 and Router version.

This is a known issue that is fixed since about 2 weeks.

https://github.com/angular/angular/issues/12740

1
votes

For anybody finding issues with redirectTo and named outlets, and stumbling on this issue. This ticket has been open since 2017 and addresses redirectTo for child routes and named outlets.

Basically, if you want your main component to redirect to the one of the children, you have 2 choices.

1) need to fill in an absolute, full path in for 'redirectTo':

https://github.com/angular/angular/issues/18271

2) if you can't do that (eg. your route is nested containing a wildcard like ':id'), you can perform a redirect via a Guard or in that parent component itself. Basically, you catch the ActivatedRouteSnapshot to see if you are on the parent itself or one of the children (you know you're on the parent if the nested 'children' array is empty) + you catch RouterStateSnapshot to see what url you are on) and then perform a 'navigateByUrl' to the url of the child you need.

canActivateChild(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean>|Promise<boolean>|boolean {
    return this.canActivate(route, state);
}


canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {

  if (route.data.redirectToChild.length) {
    const oldUrl = state.url;

    // don't want to be on a child path already,
    // so check that:
    // - we are not already on a child route
    if (route.children.length < 1) {
      const newUrl = oldUrl + '/' +  '(my-outlet:my-child-path)';
      console.log(oldUrl);
      console.log(newUrl);
      this._router.navigateByUrl(newUrl);
    }
  }
}