使用ng-view
和$routeProvider
時,可以注入$routeParams
以獲取路徑的值,如/foo/:id/:user/:item
。有什麼方法可以在路徑中設置這些參數嗎?像$routeParams.id = 3
之類的東西,然後反映在url中。
我知道這個效果可以通過$location.path()
來實現,但我希望能夠進行更高級別的抽象,不需要字符串操作。
使用ng-view
和$routeProvider
時,可以注入$routeParams
以獲取路徑的值,如/foo/:id/:user/:item
。有什麼方法可以在路徑中設置這些參數嗎?像$routeParams.id = 3
之類的東西,然後反映在url中。
我知道這個效果可以通過$location.path()
來實現,但我希望能夠進行更高級別的抽象,不需要字符串操作。
以下是我設法解決問題的方法。
控制器:
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¶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>
演示:
參考:
同樣,如果你想用$ 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);
});
}
我用這從一個共享服務,這就是爲什麼範圍在傳遞
我使用服務來創建一個雙向綁定:
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');
}]);
然後可以例如綁定一個輸入網址:
<div ng-controller="ctrl">
<input type="number" ng-model="something" />
</div>
您可能還需要設置reloadOnSearch : false
在路線的配置,因爲你不想讓控制器範圍內被摧毀和重建每當搜索位的URL變化。
我喜歡它!但請注意,這不是真正的雙向數據綁定。當函數被調用時,範圍變量被設置爲URL參數的當前值,之後,當範圍變量改變時,URL參數被更新。如果兩個作用域綁定到相同的URL參數,則更改該作用域的一個作用域不會更新另一個作用域中的變量。儘管這對於許多目的來說已經足夠 – tobek
這是真的,關於不同作用域綁定到相同的URL參數的好處。 –