How to enforce typing of route params? - javascript

I have set up the following paths:
this.resource('areaManagement', { path: '/management/areas' }, function() {
this.route('assign', { path: '/assign' });
this.route('new', { path: '/new' });
this.route('subdivide', { path: '/:id' });
});
If you wanted to create a new area, you would go to /management/areas/new, but in testing, I accidentally went to /management/areas/create and noticed no error was thrown. Then I realized, this path is matching the subdivide dynamic segment.
If this is how dynamic segments work, then technically, /management/areas/anythingyouwant will be a valid/recognized path. I could always implement a model() hook and redirect/error if :id isn't an integer, but is there a way to make the router enforce this?

I think an "easy" workaround would be to add a new nesting level by adding a
path: '/id'
to have a URL like
/management/areas/id/1
Not necessarily idealbut would help you here.

Related

Vue Routing and Regex Patterns

I'm using Vue and recently introduced a route with a parameter.
const routes = [
{
path: "/:lang(^$|^es$|^pt$|^cn$)",
name: "Home",
component: Page,
},
{
path: "/privacy",
name: "Privacy",
component: Privacy,
},
{
path: "*",
name: "NotFound",
component: NotFound,
}
];
I want the route to trigger when one of the following conditions is met.
lang is empty
lang is either es or pt or cn but no combinations of those.
Everything else should go to the NotFound route
The regex I'm using above works on the javascript engine of https://regexplanet.com
I tried all sorts and variations to make it work in Vue but to no avail so far.
I believe the path you need is:
path: "/:lang(|es|pt|cn)",
There's a routing tester here that uses the same library as Vue:
https://forbeslindesay.github.io/express-route-tester/
Make sure you're testing against path-to-regexp 0.1.7.
The problem is that the whole path gets converted to a RegExp, not just the bits in the brackets. So your ^ are never going to match anything. Try putting your original path into the testing tool to see how it compiles. The generated RegExp already contains its own ^ and $ but they are relative to the whole path, not just the parameter you're trying to match.

Change name of route path in browser only

I need to write two different routes to two pages like
{ path: 'abc', component: abcComponent},
{ path: 'abc2', component: abcComponent2},
as browser show me path:
http://localhost:4200/abc2 on accessing second route path.
Can I somehow have the same name for two components ie I want the browser to display only
http://localhost:4200/abc even if calling route path: 'abc2';
Please help me. Thanks in advance
I don't know why you need this, but if you want to do that just paste this line of code in constructor of abcComponent2 constructor:
this.router.navigateByUrl('abc', { skipLocationChange: true });
or you can also change router without changing location via html like this:
<a [routerLink]="..." skipLocationChange>click me</a>

I'm using this.$router.push to navigate programmatically, however, I'm being sent to wrong URL and I'm not sure why

I'm using nested routes so that might be causing the issue, however, I'm not sure how to fix it. I have the following route and children routes:
{
path: '/summoner/:summonerName',
component: Summoner,
children: [
{ path: '', component: Matchlist },
{ path: '/match/:matchId', component: SpecificMatch, name: 'specificMatch' }
]
},
When I'm on path /summoner/:summonerName I want to see the default Summoner parent component and the Matchlist component and when I'm on path /summoner/:summonerName/match/:matchId I want to see the default Summoner parent and the specificMatch child component. This works fine, however, when I try to use:
this.$router.push({ name: 'specificMatch', params: { summonerName: this.summoner, matchId: matchId, summonerInfo: this.summonerInfo, match: match}})
I get sent to /match/:matchId path instead of /summoner/:summonerName/match/:matchId which breaks the component because the components needs to get the username from the path. I assumed this.$router.push would send me to the correct path, alas no. Any tips how to fix this?
It's a matter of absolute and relative paths.
Your route with the name 'specificMatch' has the specified absolute path '/match/:matchId' so this is where you are navigated to. If you wish to append your path to the path of your parent route you will have to make your path relative, which means to leave out the initial slash (/) - e.i. path: 'match/:matchId'.

Rendering a child route in the parent in Angular 4

With Angular 2, I could make a child route render "over" its parent by defining an empty path and creating an essentially empty base component. I am trying to accomplish something similar with the new Angular router (version 4.3.1), but have hit a roadblock.
To reproduce my problem, here's a Plunker. The routes are defined as:
[{
path: '',
redirectTo: "/master",
pathMatch: "full"
}, {
path: 'master',
component: MasterComponent,
children: [{
path: 'detail/:value',
component: DetailComponent,
children: [{
path: 'subdetail',
component: SubDetailComponent
}]
}]
}]
When I navigate to a detail page, the master page is still visible because I have added a <router-outlet></router-outlet> to MasterComponent. What I need is to replace the master view with the detail. I can accomplish this by making detail/:value a sibling of master rather than a child, but this isn't logically correct in my application and breaks my breadcrumbs.
Is there any proper way to handle this kind of pattern, or will I have to pick a workaround, such as showing and hiding the intended route or manually specifying a dedicated "main" outlet for every link?
The only existing solution that comes close is to define a dummy parent component, but this only works one-level down. If my detail page has another sub-detail page that should also replace master, it gets very messy.
Is there any route-level flag I can set or design pattern to implement to elegantly accomplish this? I am an Angular 2 beginner, but I feel as though something like this should be simple.
First, there is no "new" router in 4.3.1. It's the same router from 2.x.
Second, there were a few changes I needed to make to your plunker to make it work appropriately. The key change was this in the master.component.ts:
<a [routerLink]="['/detail', 5]">
I added a slash. Without the slash it was looking for a route named master/detail/5
The route definition is now flat, so everything will appear "under" your main header.
export const routes: Routes = [
{
path: '',
redirectTo: 'master',
pathMatch: 'full'
},
{
path: 'master',
component: MasterComponent
},
{
path: 'detail/:value',
component: DetailComponent
}
];
The updated plunker is here: https://plnkr.co/edit/EHehUR6qSi248vQPDntt?p=preview

Ember.js Nested folder like route (contain slash)

I'm building an app with file manager like functionality with Ember.js. I'd like the URL for nested folder in the form of ".../#/files/Nested/Inside/" and it works fine with linkTo; however if I refresh (or go to the URL directly) I have the error message "No route match the URL '/files/Nested/Inside'". Is there any way to make Ember.js works in situation like this? Thanks.
Here is my current route setup:
FM.Router.map(function() {
this.resource('folders', { path: '/files' })
this.resource('folder', { path: '/files/:path' })
})
FM.FoldersRoute = EM.Route.extend({
model: function() {
return FM.Folder.find('/')
}
})
FM.FolderRoute = EM.Route.extend({
model: function(params) {
return ns.Folder.find(params.path)
},
serialize: function(folder) {
return { path: folder.get('path') }
}
})
Wow, interesting question. It should be possible but I've not tried it myself or seen any examples of this in the wild.
Under the hood, ember uses the tildeio router and route-recognizer to resolve routes. The route's readme explains how to define more elaborate routes like:
router.map(function(match) {
// this will match anything, followed by a slash,
// followed by a dynamic segment (one or more non-
// slash characters)
match("/*page/:location").to("showPage");
});
So to get nested folders working, you might be able to do something like this:
FM.Router.map(function() {
this.resource('folders', { path: '/files' })
this.resource('folder', { path: '/files/*path' })
})
Hope this helps.

Categories