-
Notifications
You must be signed in to change notification settings - Fork 3k
URL Routing
◄ Back (Multiple Named Views)
Next (The Components) ►
Most states in your application will probably have a url associated with them. URL Routing was not an after thought to the state mechanics, but was figured into the design from the beginning (all while keeping states separate from url routing)
Here's how you set a basic url.
$stateProvider
.state('contacts', {
url: "/contacts",
templateUrl: 'contacts.html'
})
Now when the user accesses index.html/contacts
then the 'contacts' state would become active and the main ui-view
will be populated with the 'contacts.html' partial. Alternatively, if the user were to transition to the 'contacts' state via transitionTo('contacts')
then the url would be updated to index.html/contacts
Often, URLs have dynamic parts to them which are called parameters. There are several options for specifying parameters. A basic parameter looks like this:
$stateProvider
.state('contacts.detail', {
url: "/contacts/:contactId",
templateUrl: 'contacts.detail.html',
controller: function ($stateParams) {
// If we got here from a url of /contacts/42
expect($stateParams).toBe({contactId: 42});
}]
})
Alternatively you can also use curly brackets:
// identical to previous example
url: "/contacts/{contactId}"
A bonus to using curly brackets is the ability to set a Regular Expression rule for the parameter:
// will only match a contactId of one to eight number characters
url: "/contacts/{contactId:[0-9]{1,8}}"
Warning: Don't put capturing parentheses into your regex patterns, the UrlMatcher in ui-router adds those itself around the entire regex. You're effectively introducing a second capture group for the same parameter, which trips up the numbering in the child URL. You can use non-capturing groups though, i.e. (?:...) is fine.
You can also specify parameters as query parameters, following a '?':
url: "/contacts?myParam"
// will match to url of "/contacts?myParam=value"
If you need to have more than one, separate them with an '&':
url: "/contacts?myParam1&myParam2"
// will match to url of "/contacts?myParam1=value1&myParam2=wowcool"
When using url routing together with nested states the default behavior is for child states to append their url to the urls of each of its parent states.
$stateProvider
.state('contacts', {
url: '/contacts',
...
})
.state('contacts.list', {
url: '/list',
...
});
So the routes would become:
-
'contacts' state matches
"/contacts"
-
'contacts.list' state matches
"/contacts/list"
. The urls were combined.
If you want to have absolute url matching, then you need to prefix your url string with a special symbol '^'.
$stateProvider
.state('contacts', {
url: '/contacts',
...
})
.state('contacts.list', {
url: '^/list',
...
});
So the routes would become:
-
'contacts' state matches
"/contacts"
-
'contacts.list' state matches
"/list"
. The urls were not combined because^
was used.
As you saw previously the $stateParams service is an object that will have one key per url parameter. The $stateParams is a perfect way to provide your controllers or other services with the individual parts of the navigated url.
// If you had a url on your state of:
url: '/users/:id/details/{type}/{repeat:[0-9]+}?from&to'
// Then you navigated your browser to:
'/users/123/details//0'
// Your $stateParams object would be
{ id:'123', type:'', repeat:'0' }
// Then you navigated your browser to:
'/users/123/details/default/0?from=there&to=here'
// Your $stateParams object would be
{ id:'123', type:'default', repeat:'0', from='there', to='here' }