Description
Squashing URLs
With the addition of optional URL parameters, UI-Router can now generate friendlier URLs. For example, with the following states created with default parameter values:
.state('user', {
url: '/user/:username',
params: { username: function(SessionService) { return SessionService.username; }
}).state('user.photos', {
url: '/gallery/:galleryid',
params: { galleryid: 0 }
}).state('user.photos.photo', {
url: "/:photoid"
});
This RFC hopes to determine the default url squashing behavior. When the user navigates to user
($state.go('user');
), the full URL with parameter included would be #/user/christopherthielen
. However, we can squash this URL down to: #/user/
or even #/user
by omitting the parameter's default value.
When the user navigates to user.photos
, the full URL with parameters would be #/user/christopherthielen/gallery/0
, but we can squash this down to: #/user//gallery/
or even #/user/gallery/
which looks even nicer.
Of course, we can transition to the same user.photos
state with non-default parameters too. Then, we cannot omit the parameter value; the URL must reflect the non-default parameters. For example, $state.go('user.photos', { username: 'someotheruser' })
will generate a full URL #/users/someotheruser/gallery/0
or a squashed version: #/users/someotheruser/gallery/
.
Squashing slashes
Omitting the slashes from the URL can potentially generate ambiguous URLs
In the above example, if we navigate as follows: $state.go('user.photos.photo', { username: 'christopherthielen', galleryid: 0, photoid: 21872 })
, the full URL (no squashing) would be: #/user/christopherthielen/gallery/0/21872
, the squashed URL would be: /#user//gallery//21872
, and the URL with slashes squashed would be: #/user/gallery/21872
.
Note that #/user/gallery/21872
(slashes squashed) is ambiguous. Is 21872
the galleryid or is it the photoid? It was intended to be photoid 21872, but if the user hit reload in their browser, they would instead return to galleryid 21872.
Here is another example from #1487. It sets up a state with 3 parameters, each with defaults.
.state('test', {
url: '/:fooid/:barid/:bazid',
params: { fooid: 123, barid: 456, bazid: 789 }
}
If we do $state.go('test', { bazid: 10000 })
and squash slashes, then the url generated is #/10000
. After a reload, that url would load state test
with param values of { fooid: 10000, barid: 456, bazid: 789 }
.
#3 Parameter Squashing options
All three parameter squash options ("nosquash"
, "value"
, "slash"
) will likely be available for use in for 0.2.12. The code to process them is in a branch, pending merging to master. You can view the branch here: https://github.com/christopherthielen/ui-router/compare/angular-ui:master...master ...
You will be able to set UI-Router's default squash policy using $urlMatcherFactoryProvider.defaultSquashPolicy()
. You will be also able to set the squash policy on individual parameters .state({ name: 'foo', url: '/foo/:fooid', params: { fooid: { value: 12345, squash: "nosquash" } } });
Default behavior? - Finally, getting to the point!
What behavior would you expect from UI-Router "Out of the box"
.state('user', {
url: '/user/:username',
params: { username: function(SessionService) { return SessionService.username; }
}).state('user.photos', {
url: '/gallery/:galleryid',
params: { galleryid: 0 }
}).state('user.photos.photo', {
url: "/:photoid"
});
With the preceding states, when an optional parameter's default values is used, should the out-of-the-box policy be to:
- (A) squash both the default parameter value and one slash. The developer is responsible to organize state urls and parameters such that ambiguous URLs cannot happen. URLs are prettier, such as
#/user/gallery/
, but the developer may not notice that they generate ambiguous URLs such as#/user/gallery/21872
. - (B) squash default parameter values only. The default behavior generates unambiguous URLs (users can refresh and return to the same state/params). The developer must explicitly choose to squash the slashes around a default parameter value. URLs are less pretty, such as
#/user//gallery//21872
but will generally map back to the state and parameters that they're generated for. - (C) Do no squash default parameter values from the URL by default. The URL is updated with the default values such as
#/user/christopherthielen/gallery/0/21872
. This is the most verbose.
Which option for UI-Router would surprise you the least?