2012-12-02 16 views
14

ng-view$routeProviderを使用する場合は、$routeParamsを入力して、パスの値を取得することができます(/foo/:id/:user/:itemなど)。パスにこれらのパラメータを設定する方法はありますか? $routeParams.id = 3のようなものをURLに反映させてください。

私はこの効果が$location.path()によって達成できることを知っていますが、私は文字列操作を必要としない抽象度を高くすることを望んでいます。

答えて

12

問題を解決する方法は次のとおりです。

コントローラ

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); 
    }]); 

モジュール宣言+ルート定義

var app = angular.module('angularjs-starter', [], [ 
     '$routeProvider', '$locationProvider', 
     function(routeProvider, locationProvider) { 
     routeProvider.when('/main', { 
      template : 'Main', 
      controller : 'MainCtrl', 
      reloadOnSearch : false 
     }); 
     } ]); 

テンプレート

<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> 

デモ

参考

1

同様に、あなたは$とURLパラメータのための双方向のデータバインディングをしたい場合場所、このsi機能が役立ちます。スコープが渡されている理由私は共有サービスからこれを使用

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); 
    }); 
} 

は、つまり、私が結合双方向を作成するサービスを利用

+1

私はそれが好きです!ただし、実際には双方向のデータバインディングではありません。関数が呼び出されると、スコープ変数はURLパラメータの現在の値に設定され、その後、スコープ変数が変更されるとURLパラメータが更新されます。 2つのスコープが同じURLパラメータにバインドされている場合、スコープを変更するスコープは他のスコープの変数を更新しません。これは多くの目的には十分です。 – tobek

+0

同じURLパラメタにバインドしている異なるスコープに関して、良い点です。 –

0

:あなたのコントローラで

angular.module('app').service('urlBinder', ['$location', function($location) { 
    this.bindOnScope = function(scope, name, urlParamName) { 
     // update the url when the scope variable changes 
     var unhookUrlUpdater = scope.$watch(name, function(newValue, oldValue) { 
      if (!angular.equals(oldValue, newValue)) { 
       $location.search(urlParamName, newValue); 
      } 
     }); 

     // update the scope variable when the url changes 
     var unhookScopeUpdater = scope.$on('$locationChangeSuccess', function() { 
      var value = $location.search()[urlParamName]; 

      if (!angular.equals(scope[name], value)) { 
       scope[name] = value; 
      } 
     }); 

     // return a function to remove the hooks. Note that since these hooks are set up on the scope passed in, if that scope gets destroyed (e.g. because the user went to a different page and the controller is no longer present), then the hooks will be removed automatically. 
     return function() { 
      unhookUrlUpdater(); 
      unhookScopeUpdater(); 
     }; 
    }; 

    // the same thing but using getter/setter functions for when you want to bind to something not on the scope 
    this.bind = function(scope, getter, setter, urlParamName) { 
     var unhookUrlUpdater = scope.$watch(getter, function(newValue) { 
      $location.search(urlParamName, newValue); 
     }); 

     var unhookScopeUpdater = scope.$on('$locationChangeSuccess', function() { 
      var value = $location.search()[urlParamName]; 

      if (!angular.equals(getter(), value)) { 
       setter(value); 
      } 
     }); 

     return function() { 
      unhookUrlUpdater(); 
      unhookScopeUpdater(); 
     }; 
    }; 
}]); 

angular.module('app').controller('ctrl', ['$scope', function($scope) { 
    // if binding to something on the scope: 
    urlBinder.bindToScope($scope, 'something', 'url-name'); 
    $scope.something = 'test'; 

    // or if the variable you want to bind isn't on the scope: 
    var someVariable; 
    urlBinder.bind(
     $scope, 
     function() { return someVariable; }, 
     function(value) { someVariable = value; }, 
     'url-name'); 
}]); 

あなたはその後、例えば、URLの入力をバインドすることができます。

<div ng-controller="ctrl"> 
    <input type="number" ng-model="something" /> 
</div> 

また、あなたは、コントローラのスコープが破壊され、URLが変更のたび検索ビット再作成することにしたくないと、あなたのルートの設定でreloadOnSearch : falseを設定する必要があるかもしれません。

関連する問題