This is relevant to me so I did a bit of work.
Here is my state that uses reloadOnSearch
but fires off a function each time the URL is updated.
.state('route2.list', {
url: "/list/:listId",
templateUrl: "route2.list.html",
reloadOnSearch: false,
controller: function($scope, $stateParams){
console.log($stateParams);
$scope.listId = $stateParams.listId;
$scope.things = ["A", "Set", "Of", "Things"];
//This will fire off every time you update the URL.
$scope.$on('$locationChangeSuccess', function(event) {
$scope.listId = 22;
console.log("Update");
console.log($location.url());
console.log($stateParams);
});
}
}
Returns in console:
Update
/route2/list/7 (index):70
Object {listId: "8"} (index):71
$locationChangeStart
and $locationChangeSuccess
should get you where you want to go. Keep in mind that your location functions will always fire off, even on the first load.
Inspiration taken from this SO post and the $location
documentation
EDIT 2
According to the Angular docs for ngRoute
, $routeParams
aren't updated until after the success of the changes. Chances are that ui-route has a similar restriction. Since we're inturrupting the resolution of the state, $stateParams
is never updated. What you can do is just emulate how $stateParams
are passed in the first place using $urlMatcherFactory
.
Like so:
.state('route2.list', {
url: "/list/:listId",
templateUrl: "route2.list.html",
reloadOnSearch: false,
controller: function($scope, $stateParams, $state, $urlMatcherFactory){
console.log($stateParams.listId + " :: " + $location.url());
$scope.listId = $stateParams.listId;
$scope.things = ["A", "Set", "Of", "Things"];
$scope.$on('$locationChangeSuccess', function(event) {
$scope.listId = 22;
//For when you want to dynamically assign arguments for .compile
console.log($state.get($state.current).url); //returns /list/:listId
//plain text for the argument for clarity
var urlMatcher = $urlMatcherFactory.compile("/route2/list/:listId");
//below returns Object {listId: "11" when url is "/list/11"}
console.log(urlMatcher.exec($location.url()));
var matched = urlMatcher.exec($location.url());
//this line will be wrong unless we set $stateParams = matched
console.log("Update " + $stateParams.listId);
console.log($location.url());
//properly updates scope.
$scope.listId = matched.listId;
});
}
})
The scope actually updates, so that's a good thing. The thing to remember is that you're stoppng the normal resolution of everything but setting reloadOnSearch
to false
so you'll need to handle pretty much everything on your own.