I’m currently working on the new dashboard for Fabrik. In Fabrik you use Portfolios to organise your Projects. It’s possible to create Projects directly and then assign them to Portfolios, or you can create a Project from a Portfolio, assigning it automatically.
In the latter scenario we need to pass the relevant Portfolio Id to our Projects controller. There are a number of ways optional parameters can be declared when using UI Router.
Query Parameters
So that query parameters are mapped to UI Router’s $stateParams
object, you need to declare them in your state configuration’s URL template:
state('new-qs', {
url: '/new?portfolioId',
templateUrl: 'new.html',
controller: function($scope, $stateParams) {
$scope.portfolioId = $stateParams.portfolioId;
}
})
You can then create a link to this state using the ui-sref
attribute:
<a ui-sref="new-qs({ portfolioId: 1 })">New (query string)</a>
This will navigate to /new?portfolioId=1
.
If you have multiple optional parameters, separate them with an &
:
state('new-qs', {
url: '/new?portfolioId¶m1¶m2',
templateUrl: 'new.html',
controller: function($scope, $stateParams) {
$scope.portfolioId = $stateParams.portfolioId;
$scope.param1 = $stateParams.param1;
$scope.param2 = $stateParams.param2;
}
})
Optional Route Parameters
Route parameters in UI Router are optional by default. This means that in the example below both /new/2
and /new/
would work, but not /new
(no trailing slash). The ?
suffix you often see on route parameters simply tells UI Router where the query portion of the URL template should start e.g. /new/:portfolioId?
.
state('new-rp', {
url: '/new/:portfolioId',
templateUrl: 'new.html',
controller: function($scope, $stateParams) {
$scope.portfolioId = $stateParams.portfolioId;
}
})
Updating the ui-sref
attribute to new-rp({ portfolioId: 2 })
will produce the link /new/2
.
If you’re not a fan of that trailing slash then you’ll need to set up another route for the parameterless version.
For multiple optional route parameters e.g. /posts/tagged/:tag/page/:page
it looks like the only solution right now is to declare multiple routes i.e. /posts/tagged/:tag
and /posts/tagged/:tag/page/:page
.
### Non-URL route parameters
Another option that I discovered recently is how to pass parameters that do not appear in the URL. This is particularly useful for abstract states.
state('new-nonurl', {
url: '/new',
params: {
portfolioId: null,
},
templateUrl: 'new.html',
controller: function($scope, $stateParams) {
$scope.portfolioId = $stateParams.portfolioId;
}
})
You can also use the params
object to declare default values for your route parameters.
Now ui-sref="new-nonurl({ portfolioId: 3 })"
will generate the link \new
but still pass the portfolioId
parameter in $stateParams
.
View the plunk demonstrating all 3 techniques here.