在AngularJS控制器之间共享数据

我试图在控制器之间共享数据。 用例是一种多步骤forms,input到一个input中的数据稍后在原始控制器之外的多个显示位置中使用。 下面的代码和jsfiddle在这里 。

HTML

<div ng-controller="FirstCtrl"> <input type="text" ng-model="FirstName"><!-- Input entered here --> <br>Input is : <strong>{{FirstName}}</strong><!-- Successfully updates here --> </div> <hr> <div ng-controller="SecondCtrl"> Input should also be here: {{FirstName}}<!-- How do I automatically updated it here? --> </div> 

JS

 // declare the app with no dependencies var myApp = angular.module('myApp', []); // make a factory to share data between controllers myApp.factory('Data', function(){ // I know this doesn't work, but what will? var FirstName = ''; return FirstName; }); // Step 1 Controller myApp.controller('FirstCtrl', function( $scope, Data ){ }); // Step 2 Controller myApp.controller('SecondCtrl', function( $scope, Data ){ $scope.FirstName = Data.FirstName; }); 

任何帮助是极大的赞赏。

一个简单的解决scheme是让你的工厂返回一个对象,让你的控制器使用同一个对象的引用:

JS:

 // declare the app with no dependencies var myApp = angular.module('myApp', []); // Create the factory that share the Fact myApp.factory('Fact', function(){ return { Field: '' }; }); // Two controllers sharing an object that has a string in it myApp.controller('FirstCtrl', function( $scope, Fact ){ $scope.Alpha = Fact; }); myApp.controller('SecondCtrl', function( $scope, Fact ){ $scope.Beta = Fact; }); 

HTML:

 <div ng-controller="FirstCtrl"> <input type="text" ng-model="Alpha.Field"> First {{Alpha.Field}} </div> <div ng-controller="SecondCtrl"> <input type="text" ng-model="Beta.Field"> Second {{Beta.Field}} </div> 

演示: http : //jsfiddle.net/HEdJF/

当应用程序变得越来越大,越来越复杂和越来越难以testing的时候,你可能不希望以这种方式从工厂公开整个对象,而是通过getter和setter给予有限的访问权限:

 myApp.factory('Data', function () { var data = { FirstName: '' }; return { getFirstName: function () { return data.FirstName; }, setFirstName: function (firstName) { data.FirstName = firstName; } }; }); 

有了这个方法,消费控制器就可以用新的值更新工厂,并观察变化以得到它们:

 myApp.controller('FirstCtrl', function ($scope, Data) { $scope.firstName = ''; $scope.$watch('firstName', function (newValue, oldValue) { if (newValue !== oldValue) Data.setFirstName(newValue); }); }); myApp.controller('SecondCtrl', function ($scope, Data) { $scope.$watch(function () { return Data.getFirstName(); }, function (newValue, oldValue) { if (newValue !== oldValue) $scope.firstName = newValue; }); }); 

HTML:

 <div ng-controller="FirstCtrl"> <input type="text" ng-model="FirstName"> <br>Input is : <strong>{{FirstName}}</strong> </div> <hr> <div ng-controller="SecondCtrl"> Input should also be here: {{FirstName}} </div> 

演示: http : //jsfiddle.net/27mk1n1o/

我不想用$watch这件事。 不是将整个服务分配给控制器的范围,而是只分配数据。

JS:

 var myApp = angular.module('myApp', []); myApp.factory('MyService', function(){ return { data: { firstName: '', lastName: '' } // Other methods or objects can go here }; }); myApp.controller('FirstCtrl', function($scope, MyService){ $scope.data = MyService.data; }); myApp.controller('SecondCtrl', function($scope, MyService){ $scope.data = MyService.data; }); 

HTML:

 <div ng-controller="FirstCtrl"> <input type="text" ng-model="data.firstName"> <br>Input is : <strong>{{data.firstName}}</strong> </div> <hr> <div ng-controller="SecondCtrl"> Input should also be here: {{data.firstName}} </div> 

或者,您可以使用直接方法更新服务数据。

JS:

 // A new factory with an update method myApp.factory('MyService', function(){ return { data: { firstName: '', lastName: '' }, update: function(first, last) { // Improve this method as needed this.data.firstName = first; this.data.lastName = last; } }; }); // Your controller can use the service's update method myApp.controller('SecondCtrl', function($scope, MyService){ $scope.data = MyService.data; $scope.updateData = function(first, last) { MyService.update(first, last); } }); 

有很多方法可以在控制器之间共享数据

  1. 使用服务
  2. 使用$ state.go服务
  3. 使用stateparams
  4. 使用rootcope

每种方法的解释:

  1. 我不会解释它已经解释过的人

  2. 使用$state.go

      $state.go('book.name', {Name: 'XYZ'}); // then get parameter out of URL $state.params.Name; 
  3. $stateparam以类似于$state.go方式$state.go ,您将其作为来自发送者控制器的对象传递,并在接收者控制器中使用stateparam

  4. 使用$rootscope

    (a)将数据从小孩发送给家长控制员

      $scope.Save(Obj,function(data) { $scope.$emit('savedata',data); //pass the data as the second parameter }); $scope.$on('savedata',function(event,data) { //receive the data as second parameter }); 

    (b)从父母向儿童pipe理员发送数据

      $scope.SaveDB(Obj,function(data){ $scope.$broadcast('savedata',data); }); $scope.SaveDB(Obj,function(data){`enter code here` $rootScope.$broadcast('saveCallback',data); }); 

我创build了一个控制pathpath模式之间共享范围的工厂,所以当用户在相同的path父path中导航时,可以维护共享数据。

 .controller('CadastroController', ['$scope', 'RouteSharedScope', function($scope, routeSharedScope) { var customerScope = routeSharedScope.scopeFor('/Customer'); //var indexScope = routeSharedScope.scopeFor('/'); } ]) 

因此,如果用户转到另一个pathpath,例如“/ Support”,path“/ Customer”的共享数据将被自动销毁。 但是,如果不是这个用户转到“子”path,比如“/ Customer / 1”或“/ Customer / list”,范围将不会被销毁。

你可以在这里看到一个例子: http : //plnkr.co/edit/OL8of9

没有使用$ watch的另一种方法是使用angular.copy:

 var myApp = angular.module('myApp', []); myApp.factory('Data', function(){ var service = { FirstName: '', setFirstName: function(name) { // this is the trick to sync the data // so no need for a $watch function // call this from anywhere when you need to update FirstName angular.copy(name, service.FirstName); } }; return service; }); // Step 1 Controller myApp.controller('FirstCtrl', function( $scope, Data ){ }); // Step 2 Controller myApp.controller('SecondCtrl', function( $scope, Data ){ $scope.FirstName = Data.FirstName; }); 

有多种方法可以做到这一点。

  1. 事件 – 已经解释得很好。

  2. UI路由器 – 上面解释。

  3. 服务 – 使用上面显示的更新方法
  4. – 看着变化。
  5. 另一个父母的孩子的方法,而不是排放brodcast

*

 <superhero flight speed strength> Superman is here! </superhero> <superhero speed> Flash is here! </superhero> 

*

 app.directive('superhero', function(){ return { restrict: 'E', scope:{}, // IMPORTANT - to make the scope isolated else we will pollute it in case of a multiple components. controller: function($scope){ $scope.abilities = []; this.addStrength = function(){ $scope.abilities.push("strength"); } this.addSpeed = function(){ $scope.abilities.push("speed"); } this.addFlight = function(){ $scope.abilities.push("flight"); } }, link: function(scope, element, attrs){ element.addClass('button'); element.on('mouseenter', function(){ console.log(scope.abilities); }) } } }); app.directive('strength', function(){ return{ require:'superhero', link: function(scope, element, attrs, superHeroCtrl){ superHeroCtrl.addStrength(); } } }); app.directive('speed', function(){ return{ require:'superhero', link: function(scope, element, attrs, superHeroCtrl){ superHeroCtrl.addSpeed(); } } }); app.directive('flight', function(){ return{ require:'superhero', link: function(scope, element, attrs, superHeroCtrl){ superHeroCtrl.addFlight(); } } }); 

在控制器之间共享数据有多种方式

  • 有angular度的服务
  • $广播方法
  • 家长之间的控制器通信
  • $ rootscope

正如我们所知, $rootscope不是数据传输或通信的首选方式,因为它是一个全局范围,可用于整个应用程序

对于angular度Js控制器之间的数据共享angular度服务是最好的做法,例如。 .factory.service
供参考

如果数据从父控制器传递到子控制器,则可以通过$scope直接访问子控制器中的父数据
如果你使用ui-router那么你可以使用$stateParmas来传递像idnamekey等url参数

$broadcast也是在控制器之间传输数据的好方法

HTML

 <div ng-controller="FirstCtrl"> <input type="text" ng-model="FirstName"> <br>Input is : <strong>{{FirstName}}</strong> </div> <hr> <div ng-controller="SecondCtrl"> Input should also be here: {{FirstName}} </div> 

JS

 myApp.controller('FirstCtrl', function( $rootScope, Data ){ $rootScope.$broadcast('myData', {'FirstName': 'Peter'}) }); myApp.controller('SecondCtrl', function( $rootScope, Data ){ $rootScope.$on('myData', function(event, data) { $scope.FirstName = data; console.log(data); // Check in console how data is coming }); }); 

请参阅给定的链接了解更多关于$broadcast

不知道我在哪里拿起这种模式,但在控制器之间共享数据,并减less$ rootScope和$范围这很好。 这是让你想起发行商和订阅者的数据复制。 希望它有帮助。

服务:

 (function(app) { "use strict"; app.factory("sharedDataEventHub", sharedDataEventHub); sharedDataEventHub.$inject = ["$rootScope"]; function sharedDataEventHub($rootScope) { var DATA_CHANGE = "DATA_CHANGE_EVENT"; var service = { changeData: changeData, onChangeData: onChangeData }; return service; function changeData(obj) { $rootScope.$broadcast(DATA_CHANGE, obj); } function onChangeData($scope, handler) { $scope.$on(DATA_CHANGE, function(event, obj) { handler(obj); }); } } }(app)); 

获取新数据的控制器,即发布者将执行此类操作。

 var someData = yourDataService.getSomeData(); sharedDataEventHub.changeData(someData); 

也使用这个新数据的控制器,这就是所谓的订阅者会做这样的事情…

 sharedDataEventHub.onChangeData($scope, function(data) { vm.localData.Property1 = data.Property1; vm.localData.Property2 = data.Property2; }); 

这将适用于任何情况。 因此,当初始化主控制器并获取数据时,它将调用changeData方法,然后将该数据广播给该数据的所有订阅者。 这减less了我们的控制器之间的耦合。

只要做到这一点(使用v1.3.15testing):

 <article ng-controller="ctrl1 as c1"> <label>Change name here:</label> <input ng-model="c1.sData.name" /> <h1>Control 1: {{c1.sData.name}}, {{c1.sData.age}}</h1> </article> <article ng-controller="ctrl2 as c2"> <label>Change age here:</label> <input ng-model="c2.sData.age" /> <h1>Control 2: {{c2.sData.name}}, {{c2.sData.age}}</h1> </article> <script> var app = angular.module("MyApp", []); var dummy = {name: "Joe", age: 25}; app.controller("ctrl1", function () { this.sData = dummy; }); app.controller("ctrl2", function () { this.sData = dummy; }); </script>