[英]How do I update the view from a different controller in angular.js without using directive?
我有一個角度應用程序,頁面上有2個部分。
1部分是側欄,給出了一個概要。 我們說它說:
Players 5 // {{ numOfPlayers }}
代碼是一個ajax調用。 我不想增加,因為這個號碼可以通過另一個呼叫增加。 我需要在獲取數組長度之后運行ajax調用。
angular.module('app').controller('nav', function($scope,$http) {
$http.get('/players').then(function(data) {
$scope.numOfPlayers = data.players.length;
});
});
現在位於主頁面上的完全獨立的控制器中。 用戶可以添加播放器。 我如何擁有它以便我可以更新導航控制器?
angular.module('app').controller('mainController', function($scope,$http) {
$http.post(.....).then(function(data) {
//update the numOfPlayers so the nav is updated.
});
});
您可以使用服務來保存共享數據和$watch
更改:
var app = angular.module('TestApp', []); app.service("playersService", function () { this.numOfPlayers = 0; }); app.controller("navController", function ($scope, $http, playersService) { // Update the shared resource initial value with GET result // $http.get('/players').then(function(data) { // playersService.numOfPlayers = response.data.length; // }); playersService.numOfPlayers = 0; $scope.$watch(function () { return playersService.numOfPlayers; }, function (value) { $scope.numOfPlayers = value; }); }); app.controller("mainController", function ($scope, playersService) { $scope.addPlayer = function () { // POST and update the shared resource with result // $http.post(.....).then(function(data) { playersService.numOfPlayers++; } });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="TestApp"> <section ng-controller="navController"> <h1>Nav</h1> Players {{ numOfPlayers }} </section> <section ng-controller="mainController"> <h1>Main</h1> <button ng-click="addPlayer()"> Add player </button> </section> </div>
您可以使用父控制器(比如pageController)來保存共享數據:
var app = angular.module('TestApp', []); app.controller("pageController", function ($scope) { $scope.numOfPlayers = null; }); app.controller("mainController", function ($scope, $http) { $scope.addPlayer = function () { // POST and update the shared resource with result // $http.post(.....).then(function(data) { $scope.$parent.numOfPlayers++; }; }); app.controller("navController", function ($scope, $http) { // Update the shared resource initial value with GET result // $http.get('/players').then(function(data) { // $scope.$parent.numOfPlayers = response.data.length; // }); $scope.$parent.numOfPlayers = 0; });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="TestApp" ng-controller="pageController"> <section ng-controller="navController"> <h1>Nav</h1> Players {{ numOfPlayers }} </section> <section ng-controller="mainController"> <h1>Main</h1> <button ng-click="addPlayer()"> Add player </button> </section> </div>
附注:
在兩種方法中:
可能更好地將player數組用作共享資源。 在這個例子中,我試圖保持簡單。
可能更好地從mainController
而不是navController
更新初始資源值。 在示例中,我嘗試與您的代碼保持一致。
首先,我建議使用最佳實踐並使用組件而不是ng-controller。
所以你有2個組成部分:
angular.module('app').component('nav', {});
和
angular.module('app').component('main', {});
現在,您可以通過服務在它們之間共享狀態數據:
angular.module('app').service('PlayersService', function(){
this.players = [];
this.getAll() = () => {};
this.add(player) = () => {};
});
只有一個棘手的部分是你需要在所有組件中觀察 玩家的變化:
angular.module('app').component('nav', {
controller: function($scope, PlayersService){
PlayersService.getAll();
$scope.$watch(() => PlayersService.players.length, (playersLength) => this.numOfPlayers = playersLength)
}
});
angular.module('app').component('main', {
controller: function($scope, PlayersService){
//PlayersService.add(player);
$scope.$watch(() => PlayersService.players.length, (playersLength) => this.numOfPlayers = playersLength)
}
});
因此,在兩種情況下,范圍屬性numOfPlayers都會更新。
由於您在一個頁面上有兩個部分,我的建議是使用一個或多個組件而不是單獨的控制器。 示例如下:
angular .module('exampleApp', []) .controller('ExampleController', ExampleController); function ExampleController() { var vm = this; vm.numPlayers = 0; } angular .module('exampleApp') .component('playerSummary', { bindings: { numPlayers: '<' }, template: `<p>{{ $ctrl.numPlayers }}</p>` }); angular .module('exampleApp') .component('playerAddition', { bindings: { numPlayers: '=' }, controller: function() { function addPlayer() { this.numPlayers++; } this.addPlayer = addPlayer; }, template: `<button type="button" ng-click="$ctrl.addPlayer()">+</button>` });
<!DOCTYPE html> <html ng-app='exampleApp'> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular.min.js"></script> </head> <body ng-controller="ExampleController as vm"> <player-summary num-players="vm.numPlayers"></player-summary> <player-addition num-players="vm.numPlayers"></player-addition> </body> </html>
不推薦,但您也可以使用$ rootScope或catch和emit事件。
您還可以綁定到服務屬性,例如下面的示例,或直接綁定到服務。
angular .module('exampleApp', []); angular .module('exampleApp') .controller('FirstController', FirstController); function FirstController(PlayerService) { var vm = this; vm.players = PlayerService.players; } FirstController.$inject = ['PlayerService']; angular .module('exampleApp') .controller('SecondController', SecondController); function SecondController(PlayerService) { var vm = this; vm.addPlayer = function() { PlayerService.addPlayer(); } } SecondController.$inject = ['PlayerService']; angular .module('exampleApp') .service('PlayerService', PlayerService); function PlayerService() { var PlayerService = this; PlayerService.players = []; PlayerService.addPlayer = function() { PlayerService.players.push({}); } }
<!DOCTYPE html> <html ng-app='exampleApp'> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular.min.js"></script> </head> <body> <div ng-controller="FirstController as vm"> <p>{{vm.players.length}}</p> </div> <div ng-controller="SecondController as vm"> <button ng-click="vm.addPlayer()">+</button> </div> </body> </html>
正如Khalil Malki所說,你可以看到服務價值
正如Jaqen H'ghar所說,你可以使用父控制器。
你可以使用angular.factory()
來做到這angular.factory()
或angular.service(); or $localStorage and or $sessionStorage
angular.service(); or $localStorage and or $sessionStorage
。
首先進行全局調用而不是在控制器內調用:
例:
angular.factory('updateVal', function(){
var data;
return {
getPlayers: function(){
return $http.get('/players').success(function(results){
data = results;
return data;
});
},
setPlayers: function(val){
if(val){
data = val;
return data;
}
else {
return data;
}
}
}
});
在你的控制器:第一控制器
angular.module('app').controller('nav', function($scope,updateVal){
$scope.numOfPlayers = updateVal.getPlayers();
$scope.$watch(function(){
return updateVal.setPlayers().length > 0;
}, function(){
$scope.numOfPlayers = updateVal.setPlayers();
})
})
第二控制器:
angular.module('app').controller('mainController', function($scope,$http,updateVal) {
// this function update the players updateVal.getPlayers();
$http.post(.....).then(function(data) {
//update the numOfPlayers so the nav is updated.
// after posting call this function:
updateVal.setPlayers(data);
});
});
使用angular.service:
這可以做到:
angular.service('updatePlayers', function(){
var updatedPlayers;
this.setPlayers = function(args){
updatedPlayers = args;
}
this.getPlayers = function(){
return updatedPlayers;
}
})
在你的第一個控制器:
angular.module('app').controller('nav', function($scope,$http,updatePlayers) {
$http.get('/players').then(function(data) {
updatePlayers.setPlayers(data.players.length);
$scope.numOfPlayers = data.players.length;
});
});
在第二個控制器中:
angular.module('app').controller('mainController', function($scope,$http,updatePlayers) {
$http.post(.....).then(function(data) {
//update the numOfPlayers so the nav is updated.
updatePlayers.getPlayers();
});
});
編輯修復錯字
更好的方法是兩個有兩個指令:
page
指令 nav
指令 nav
指令將一些數據作為輸入。 在這種情況下,玩家的數量可以是輸入之一。 然后,當您將nav
指令嵌套在page
指令中時,您可以將數據從page
傳遞到nav
並且當值更改時nav
將自動更新:
HTML
<page></page>
JavaScript的
app.directive('page', function() {
return {
restrict: 'E',
controller: function($scope, playerSvc) {
playerSvc.getPlayers.then(function(resp) {
$scope.players = resp.data;
});
},
template: '<header> blah</header> <nav player-count="players.length"></nav> <footer></footer>'
};
});
app.directive('nav', function() {
return {
restrict: 'E',
scope: { playerCount: '=' },
template: '<div> player count: {{playerCount}} </div>'
};
});
通過這樣做,您可以隔離指令(組件)並創建清晰的邊界。 每個組件或指令都有一個小的責任。 在這種情況下, nav
獲取一些數據並顯示它們,並且還負責導航。 page
指令為頁面上的不同組件或指令提供全局數據。 您可以使用相同的想法並決定誰將玩家添加到玩家列表中。 並且因為nav
指令連接到players.length
,所以一旦players
更新,它將自動更新。
也許在nav控制器中調用方法,以便范圍變量更新,最終通過雙向綁定更新視圖
angular.module('app').controller('nav', function($scope,$http) {
$rootScope.$on("CallMethodNavController", function(){
$scope.navMethod();
});
$scope.CallMethodNavController=function(){
$http.get('/players').then(function(data) {
$scope.numOfPlayers = data.players.length;
}
});
});
然后在第二個控制器中,一旦添加了一個播放器就調用此方法:
$rootScope.$emit("CallMethodNavController", {});
無需為此創建手表或活動。
使用服務獲取,存儲,更新和共享應用程序中的玩家陣列。
而不是創建長度的原始變量...存儲對控制器和視圖中的數組的引用執行{{players.length}}
並讓角度視圖觀察者負責更新。
angular.module('app').factory('playersService', function($http){
// now have an array to share across app
// and reference to addPlayer function
var factory ={players:[], addPlayer: addPlayer };
// load the players and add them to array
$http.get('/players').then(function(response) {
Array.prototype.push.apply(factory.players, response.data);
});
function addPlayer(player){
return $http.post(url, player).then(function(resp){
// add new player to shared array
factor.push(resp.data);
}
}
return factory;
});
導航控制器
angular.module('app').controller('nav', function($scope,playersService) {
$scope.players = playersService.players; // store full array reference
});
導航視圖
Number Players: {{players.length}} <!-- angular will automatically watch and update -->
其他控制器
angular.module('app').controller('mainController', function($scope,playersService) {
$scope.newPlayer={};// bind to ng-model's in form
$scope.saveNewPlayer = function(){
playersService.addPlayer($scope.newPlayer).then(function(){
alert('Number of players in nav will already be updted');
// clear form
$scope.newPlayer={};
})
});
});
使用$ emit和$ on來自主cintroller $ rootScope。$ broadcast('update','status'){$ http.post(.....)。then(function(data){//更新numOfPlayers所以導航已更新。});}
and in your nav controller use
$scope.$on('eventName', function (event, args) { $http.get('/players').then(function(data) {
$scope.numOfPlayers = data.players.length;});});
$ broadcast從父節點傳送到子節點,因此父控制器中的任何更改都將反映在子控制器中
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.