簡體   English   中英

如何在不使用指令的情況下從angular.js中的其他控制器更新視圖?

[英]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> 


附注:

在兩種方法中:

  1. 可能更好地將player數組用作共享資源。 在這個例子中,我試圖保持簡單。

  2. 可能更好地從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();
    });
});

編輯修復錯字

更好的方法是兩個有兩個指令:

  1. page指令
  2. 一個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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM