Skip to content

RFC: Default URL generation for optional parameters  #1501

Closed
@christopherthielen

Description

@christopherthielen

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions