1

I'm currently using ui-router to manage my routes in my angularjs app, and I was wondering if there was a way to modify the url that gets created.

Its better explained with an example. I have the following state

$stateProvider.state('items', { url: 'items/{itemName}', ... }); 

Then in my view I can transition to this state with

<a ui-sref="items({itemName:'Full Item Name'})">...</a> 

which, when clicked, to set the url to /items/Full%20Item%20Name What I would like to do is modify the url that will be generated to /items/full-item-name, but still have Full Item Name show up in the $stateParams.

I have managed to change the navigated url to what I wanted using

$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) { for (var prop in toParams) { var original = toParams[prop]; var pretty = makePretty(original); toParams[prop] = pretty; } }); 

This will change the toParams to their 'prettified' form before the route change happens so that the url will be what I want

Here is a plunk: http://plnkr.co/edit/8AhkitxFjy7H6ZwTkeT4?p=preview

The main thing that I am missing right now is the url that is pointed to by the link is still items/Full%20Item%20Name.

Am I missing something? Is there an easier way to approach this?

2 Answers 2

1

We have a feature called typed parameters coming in a future version that will allow you to do this, but for now, the only two things I could suggest would be something like this:

<a ui-sref="items({ itemName: slug('Full Item Name') })">...</a>

and then:

onEnter: function($stateParams) { $stateParams.itemName = deslug($stateParams.itemName) } 

Or alternatively, to do it globally, override $state.href() (but you'd probably still need to do the onEnter thing).

Sign up to request clarification or add additional context in comments.

2 Comments

I was originally trying to keep the slug call out of my view, but it seems to work for now. I'll try to override the href call in a bit and see where that gets me. Unslugging the values in onEnter doesn't work, as it is called after the resolves and before the url gets set to the browser. Right now I am unslugging the values returned from my resolve calls, and resetting the toParams in $stateChangeSuccess.
Is this somehow supported in the current version, 0.2.13?
0

Using the recommendations from Nate, here is my solution:

app.run(function($rootScope, $state) { // Store a copy of the original href function $state.baseHref = $state.href; $state.href = function href(stateOrName, params, options) { // slug each parameter that comes in for (var p in params) { params[p] = slug(params[p]); } // then call the original href function with the slugged params return $state.baseHref(stateOrName, params, options); }; $rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) { // After the state has changed unslug the parameters so that // $stateParams.parameterName is the unslugged value for (var prop in toParams) { toParams[prop] = unslug(toParams[prop]); } }); }); 

This solves creates slugged urls, and unslugs them after the state has transitioned but before the controller gets created. One thing to note is that $stateChangeSuccess is fired after the resolve properties are fulfilled, so in order to get the unslugged values in resolve I had to do the following:

resolve: { parameterName: function ($stateParams) { return unslug($stateParams.parameterName); } } 

If you are just injecting $stateParams into your controller, you can skip the last step.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.