Using the @angular/router
version 3.0.0-beta.2
I would like to build an application which allows my users to browse a filesystem.
The following illustrates the types of URL 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 struggling to come up with a mechanism to configure this using RouterConfig
.
{ path: 'browse/:path', component: BrowserComponent }
This RouterConfig
only supports a single subdirectory, i.e. browse/animals
. However, if I attempt to browse to the second-level of subdirectory /browse/animals/mammals
I get the following error:
Error: Cannot match any routes: '/browse/animals/mammals'
I understand that the default behaviour of a parameter in the router (in this case :path
) is to "break" on the first forward slash, and assume the following token is a sub-path.
How can I configure the router to allow the :path
parameter to accept forward slashes / "gobble" the entire remaining URL as the parameter?
How can I deal with the use-case where the user wishes to browse the root directory, i.e. the URL /browse
. This will not match the router configuration described above, as the :path
parameter is not present.
I have attempted to work around this using two distinctly configured router paths:
{ path: 'browse', component: BrowserComponent },
{ path: 'browse/:path', component: BrowserComponent }
However, this is causing me problems with routerLinkActive
. I have a main menu with a link to the browser, that looks like this:
<a [routerLink]="['/browse']" [routerLinkActive]="['active']">...</a>
I would like this main menu link to have the active
class if the user has browsed to the root /browse
or to some subdirectory /browse/animals/
.
However, given the /browse/animals/
URL is not a child of the /browse
route, it does not become active
.
I cannot make the :path
parameter route a child of the /browse
root, as there is no need for a nested view, and it results in:
Cannot find primary outlet to load BrowserComponent
The path refers to the part of the URL that determines a unique view that should be displayed, and component refers to the Angular component that needs to be associated with a path. Based on a route definition that we provide (via a static RouterModule.
Route parameters are named URL segments that are used to capture the values specified at their position in the URL. The captured values are populated in the req. params object, with the name of the route parameter specified in the path as their respective keys.
Building on the **
suggestion from @DaSch, it is indeed possible to use the wildcard route:
{ path: '/browse', component: BrowserComponent, children: [ { path: '**' } ] }
There is no need to have a nested router-outlet
within the BrowserComponent
as there is no component
field specified on the child path.
As desired, the BrowserComponent will now be routed for all the described URLs:
http://myapp/browse
http://myapp/browse/animals
http://myapp/browse/animals/mammals
The challenge now is to obtain the par tof the URL which represents the path that the browser has navigated to, and subscribe to changes as the user navigates.
I have prototyped this using the 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);
}
}
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With