[英]How to force view updates in angularjs by services?
我試圖持有一個提供導航菜單的全局MainCtrl
控制器。 這些菜單項應不時由各種控制器進行更新。
現在,我想我可以將導航鏈接綁定到控制器,並按如下所示更新控制器變量:
<div ng-controller="MainCtrl">
<li ng-repeat="nav in navigations">
<a href="#{{nav.path}}">{{nav.label}}</a>
</li>
</div>
<div ng-view></div> <!-- renders different controllers, eg testController.js -->
app.controller('MainCtrl', ['$scope', 'navigationService', function($scope, navigationService) {
//binding the property of the service
$scope.navigations = navigationService.navigations;
}]);
app.service('navigationService', function() {
return {
navigations: null
};
});
但是,當調用服務並更新內部的navigations
變量時,視圖中沒有任何更改。 為什么?
angular.module('test').controller('testController', ['$scope', '$http', 'navigationService', function($scope, $http, navigationService) {
$http.get(url)
.success(function(data) {
navigationService.navigations = data.some.navigations; //assume json data exists
});
}]);
如何實現這種雙向數據綁定,迫使視圖從一個控制器更新到另一個?
您正在從服務中返回primitive
。 基本體沒有繼承。
而是返回一個對象:
app.service('navigationService', function() {
var nav ={}; // object that will be returned
function init(){
$http.get(url)
.success(function(data) {
// modify object returned from service rather than reassign a primitive value
nav.items = data.some.navigations; exists
});
}
init();//make request to load the data
return { // can add more properties if needed
nav: nav
};
});
然后在控制器中:
$scope.navigations = navigationService.nav;
// will initially be {} and later will inherit items property
視野中
<div ng-repeat="item in navigations.items">
有角度的內部手表將拾取現在對對象所做的更改並相應地渲染視圖
使用Angular超過2年后,我發現,每當您想要具有來自不同服務/控制器/指令的多重綁定的功能時,總會使用json屬性,並且永遠不要使用ovverride變量實例:
我將替換為:
$scope.navigations = navigationService.navigations;
接着就,隨即:
var state = {
navigations: []
};
$scope.state = state;
state.navigations = navigationService.navigations; // i prefer such syntax
// or
$scope.state.navigations = navigationService.navigations;
為什么? 可能是由於Angular自動將$ watch()/ $ watchCollection()函數綁定到變量更改。
您需要使用$ rootscope進行廣播,並注意廣播
假設您的數據已從x控制器更改,因此您可以在此處像這樣廣播
$rootScope.$broadcast('menu-need-to-refresh');
在您的主控制器中,像這樣
$scope.$on('menu-need-to-refresh', function (event, data) {
$scope.menus= service.newMenu();
});
希望對您有幫助
更新 :@charlietfl + @Dmitri Algazin方法更優雅,因為它通過使用引用來利用javascript本身,並避免在控制器+ ngRepeat中使用兩個觀察程序(此指令中的watchCollection將完成工作)。
我的原始答案:
您應該使用$scope.$watch
從MainCtrl
監視服務中的更改:
app.controller('MainCtrl', ['$scope', 'navigationService', function($scope, navigationService) {
//binding the property of the service
$scope.$watch(
function(){
return navigationService.navigations;
}
, function(newValue, oldValue){
if(newValue !== oldValue){
$scope.navigations = newValue;
}
})
}]);
我只是通過使用$ scope。$ watch解決了類似的問題。
例如: $scope.$watch( function(){return navigationService.navigations;}, function(newVal, oldVal){$scope.navigations = newVal;} )
此代碼未經測試,但您可以$scope.$watch( function(){return navigationService.navigations;}, function(newVal, oldVal){$scope.navigations = newVal;} )
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.