When using ng-view
and $routeProvider
, it's possible to inject $routeParams
to get values of the path, like /foo/:id/:user/:item
. Is there any way to set those parameters in the path? Something like $routeParams.id = 3
, and then have that reflected in the url.
I know this effect could be achieved through $location.path()
, but I'm hoping to for a higher level of abstraction that doesn't require string manipulation.
Here's how I managed to solve the problem.
Controller:
app.controller('MainCtrl', [
'$scope', '$log', '$route', '$routeParams', '$location',
function(scope, console, route, routeParams, location) {
console.log('MainCtrl.create');
scope.route = route;
scope.routeParams = routeParams;
scope.location = location;
//1. This needs to be enabled for each controller that needs to watch routeParams
//2. I believe some encapsulation and reuse through a service might be a better way
//3. The reference to routeParams will not change so we need to enable deep dirty checking, hence the third parameter
scope.$watch('routeParams', function(newVal, oldVal) {
angular.forEach(newVal, function(v, k) {
location.search(k, v);
});
}, true);
}]);
Module declaration + route definition:
var app = angular.module('angularjs-starter', [], [
'$routeProvider', '$locationProvider',
function(routeProvider, locationProvider) {
routeProvider.when('/main', {
template : 'Main',
controller : 'MainCtrl',
reloadOnSearch : false
});
} ]);
Template:
<body ng-controller="MainCtrl">
<a href="#/main">No Params</a>
<a href="#/main?param1=Hello¶m2=World!">With Params</a>
<div ng-view></div>
<p>
<span>param1</span>
<input type="text" ng-model="routeParams['param1']">
</p>
<p>
<span>param2</span>
<input type="text" ng-model="routeParams['param2']">
</p>
<pre>location.path() = {{location.path()}}</pre>
<pre>routeParams = {{routeParams}}</pre>
</body>
Demo:
References:
As well, if you want two-way databinding for url parameters with $location, this simple function will help.
bind_var_to_urlparam = function(variable_name, scope){
// initial loading from urlparams and then
// set a watch function to update the urlparams on update
scope[variable_name] = $location.search()[variable_name];
scope.$watch(variable_name, function(newVal, oldVal){
var search_obj = {};
search_obj[variable_name] = newVal;
$location.search(search_obj);
});
}
I use this from a shared service, that is why scope is passed in.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With