Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two-way binding with $routeParams?

Tags:

angularjs

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.

like image 900
Nick Heiner Avatar asked Dec 02 '12 19:12

Nick Heiner


2 Answers

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&param2=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:

  • plunker

References:

  • routeParams
like image 140
Liviu T. Avatar answered Oct 16 '22 17:10

Liviu T.


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.

like image 41
David Merritt Avatar answered Oct 16 '22 17:10

David Merritt