Angular2 Routing Path Style Parameters

Using @angular/router version 3.0.0-beta.2 , I would like to create an application that allows my users to view the file system.

The following are the types of URLs that I would like to support:

 http://myapp/browse <--- Browse without parameters, lists root dir http://myapp/browse/animals <--- Browse "animals" subdirectory http://myapp/browse/animals/mammals <--- Browse "animals/mammals" subdirectory 

I am trying to create a mechanism for configuration using RouterConfig .


Path Style Options

 { path: 'browse/:path', component: BrowserComponent } 

This RouterConfig supports only one subdirectory, i.e. browse/animals . However, if I try to go to the second level subdirectory /browse/animals/mammals , I get the following error:

 Error: Cannot match any routes: '/browse/animals/mammals' 

I understand that the default behavior of the parameter in the router (in this case :path ) means to “split” the first forward slash and assume that the next token is a subpath.

How to configure the router so that :path accepts a forward slash / gobbles up the remaining URL as a parameter?


Optional parameter

How can I deal with a use case when a user wants to view the root directory, i.e. URL /browse . This will not match the router configuration described above, because the :path parameter :path missing.

I tried to get around this using two well-tuned router paths:

 { path: 'browse', component: BrowserComponent }, { path: 'browse/:path', component: BrowserComponent } 

However, this causes me problems with routerLinkActive . I have a main menu with a link to a browser that looks like this:

 <a [routerLink]="['/browse']" [routerLinkActive]="['active']">...</a> 

I would like this link in the main menu to have an active class if the user looked at the root directory /browse or in some subdirectory /browse/animals/ .

However, if the URL /browse/animals/ not a child of the /browse route, it does not become active .

I cannot make the :path parameter route the child of the /browse root, as there is no need for a nested view, and this results in:

 Cannot find primary outlet to load BrowserComponent 
+5
source share
5 answers

Based on the ** suggestion from @DaSch, it's really possible to use a lookup pattern:

 { path: '/browse', component: BrowserComponent, children: [ { path: '**' } ] } 

There is no need to have a nested router-outlet in the BrowserComponent , since the component field is not specified on the child path.

Optionally, the BrowserComponent will now be routed for all the URLs described:

 http://myapp/browse http://myapp/browse/animals http://myapp/browse/animals/mammals 

Now the challenge is to get the URL pair that represents the path that the browser is moving to and subscribe to the changes as the user navigates.

I prototype this using Router :

 router.events.filter(e => e instanceof NavigationEnd) .forEach((event: NavigationEnd) => { // The root route belongs to "/browse" let parentRoot: ActivatedRoute = router.routerState.root.firstChild; if (parentRoot.snapshot.url.map(p => p.path).join("/") == "/browse") { let path: string = ""; // Child route is optional, in case the user has browsed to just "/browse" let childRoute: ActivatedRoute = parentRoot.firstChild; if (childRoute) { path = childRoute.snapshot.url.map(p => p.path).join("/"); console.log("New browser path is ", path); } this.loadPath(path); } } ); 
+7
source

I have not tried this, but from the documentation I would try to use children with a wildcard selector.

 { path: 'browse', component: ..., children: [ path: '**', component: ... ]}, 

Just guess, and I will need to check how to get the path parameters in order to get the right content for the given path.

+5
source

You can try it like this.

Just using your first route: { path: 'browse', component: BrowserComponent }

And for folder names using the so-called optional routes .

The link must contain this syntax:

<a [routerLink]="['/browse', ['f1', 'f2', 'f3', 'f4'] ]">--link name--</a>

or like this:

<a [routerLink]="['/browse', { folders: ['f1', 'f2', 'f3', 'f4'] } ]">--link name--</a>

Enter private _route: ActivatedRoute in the component constructor and subscribe to the parameters:

 this._route.params.subscribe( val => console.log(val), err => console.log(err)); 

The first will print the following: Object {0: "f1", 1: "f2", 2: "f3", 3: "f4"} and the second will print this: Object {folders: "f1,f2,f3,f4"}

Or maybe you get another idea to add your folders using this optional parameters .. gl! :)

0
source

You can configure the router dynamically as described in fooobar.com/questions/1253345 / ...

 router.resetConfig([ { path: 'team/:id', component: TeamCmp, children: [ { path: 'simple', component: SimpleCmp }, { path: 'user/:name', component: UserCmp } ] } ]); 

https://github.com/angular/angular/issues/11437#issuecomment-245995186 provides RC.6 Plunker

-1
source

May be useful, router.resetConfig() works router.resetConfig() for me with new route rules in the user logic of my application

-1
source

All Articles