AngularJS:我怎样才能在控制器之间传递variables?

我有两个angular控制器:

function Ctrl1($scope) { $scope.prop1 = "First"; } function Ctrl2($scope) { $scope.prop2 = "Second"; $scope.both = Ctrl1.prop1 + $scope.prop2; //This is what I would like to do ideally } 

我不能在Ctrl2使用Ctrl2因为它是未定义的。 但是,如果我试图通过它像这样…

 function Ctrl2($scope, Ctrl1) { $scope.prop2 = "Second"; $scope.both = Ctrl1.prop1 + $scope.prop2; //This is what I would like to do ideally } 

我得到一个错误。 有谁知道如何做到这一点?

 Ctrl2.prototype = new Ctrl1(); 

也失败了。

注意:这些控制器没有嵌套在一起。

在多个控制器之间共享variables的一种方法是创build一个服务,并将其注入到要使用它的任何控制器中。

简单的服务例子:

 angular.module('myApp', []) .service('sharedProperties', function () { var property = 'First'; return { getProperty: function () { return property; }, setProperty: function(value) { property = value; } }; }); 

在控制器中使用该服务:

 function Ctrl2($scope, sharedProperties) { $scope.prop2 = "Second"; $scope.both = sharedProperties.getProperty() + $scope.prop2; } 

这个在这个博客中很好地描述(第2课,特别是)。

我发现,如果你想跨多个控制器绑定到这些属性,如果你绑定到一个对象的属性,而不是原始types(布尔,string,数字)来保留绑定参考,它会更好。

例如: var property = { Property1: 'First' }; 而不是var property = 'First';


更新:(希望)让事情更清楚这里是一个小提琴 ,显示了一个例子:

  • 绑定到共享值的静态副本(在myController1中)
    • 绑定到一个原始(string)
    • 绑定到一个对象的属性(保存到一个范围variables)
  • 绑定到更新UI的共享值(更新值在myController2中)
    • 绑定到一个函数,返回一个基元(string)
    • 绑定到对象的属性
    • 双向绑定到对象的属性

我喜欢用简单的例子来说明简单的事情:)

这是一个非常简单的Service示例:

 angular.module('toDo',[]) .service('dataService', function() { // private variable var _dataObj = {}; // public API this.dataObj = _dataObj; }) .controller('One', function($scope, dataService) { $scope.data = dataService.dataObj; }) .controller('Two', function($scope, dataService) { $scope.data = dataService.dataObj; }); 

这里的jsbin

这里是一个非常简单的Factory例子:

 angular.module('toDo',[]) .factory('dataService', function() { // private variable var _dataObj = {}; // public API return { dataObj: _dataObj }; }) .controller('One', function($scope, dataService) { $scope.data = dataService.dataObj; }) .controller('Two', function($scope, dataService) { $scope.data = dataService.dataObj; }); 

这里的jsbin


如果这太简单了, 这是一个更复杂的例子

另请参阅相关最佳实践评论的答案

—我知道这个答案不是针对这个问题的,但是我想要读这个问题的人想要处理像工厂这样的服务,

为此,您将需要使用服务或工厂。

这些服务是在不嵌套的控制器之间共享数据的最佳实践

关于数据共享这个主题的一个非常好的注释是如何声明对象。 我很不走运,因为在我读完之前,我陷入了AngularJS陷阱,而且我非常沮丧。 所以让我帮你避免这个麻烦。

我从“ng-book:AngularJS上的完整书”中读到,在控制器中创build的AngularJS ng-models作为裸数据是错误的!

$ scope元素应该像这样创build:

 angular.module('myApp', []) .controller('SomeCtrl', function($scope) { // best practice, always use a model $scope.someModel = { someValue: 'hello computer' }); 

而不是这样的:

 angular.module('myApp', []) .controller('SomeCtrl', function($scope) { // anti-pattern, bare value $scope.someBareValue = 'hello computer'; }; }); 

这是因为它是build议(BEST PRACTICE)DOM(html文档)包含调用

 <div ng-model="someModel.someValue"></div> //NOTICE THE DOT. 

如果您希望您的子控制器能够从父控制器更改对象,这对于嵌套控制器非常有用….

但在你的情况下,你不需要嵌套的作用域,但是有一个类似的方面来从服务中获取对象到控制器。

比方说,你有你的服务“工厂”,并在返回空间有一个objectA包含objectB包含objectC。

如果你想从你的控制器中获取objectC到你的范围内,是错误的说:

 $scope.neededObjectInController = Factory.objectA.objectB.objectC; 

这不会工作…而是只使用一个点。

 $scope.neededObjectInController = Factory.ObjectA; 

然后,在DOM中,您可以从objectA调用objectC。 这是与工厂有关的最佳做法,最重要的是, 这将有助于避免意外和不可捕捉的错误。

解决scheme无需创build服务,使用$ rootScope:

要跨应用程序控制器共享属性,您可以使用Angular $ rootScope。 这是分享数据的另一种select,让人们知道这一点。

跨控制器共享某些function的首选方法是服务,以读取或更改全局属性,您可以使用$ rootcope。

 var app = angular.module('mymodule',[]); app.controller('Ctrl1', ['$scope','$rootScope', function($scope, $rootScope) { $rootScope.showBanner = true; }]); app.controller('Ctrl2', ['$scope','$rootScope', function($scope, $rootScope) { $rootScope.showBanner = false; }]); 

在模板中使用$ rootScope(使用$ root的访问属性):

 <div ng-controller="Ctrl1"> <div class="banner" ng-show="$root.showBanner"> </div> </div> 

上面的例子像一个魅力。 我只是做了一个修改,以防万一我需要pipe理多个值。 我希望这有帮助!

 app.service('sharedProperties', function () { var hashtable = {}; return { setValue: function (key, value) { hashtable[key] = value; }, getValue: function (key) { return hashtable[key]; } } }); 

我倾向于使用价值观,为任何人开心讨论为什么这是一个坏主意。

 var myApp = angular.module('myApp', []); myApp.value('sharedProperties', {}); //set to empty object - 

然后按照服务注入值。

在ctrl1中设置:

 myApp.controller('ctrl1', function DemoController(sharedProperties) { sharedProperties.carModel = "Galaxy"; sharedProperties.carMake = "Ford"; }); 

并从ctrl2访问:

 myApp.controller('ctrl2', function DemoController(sharedProperties) { this.car = sharedProperties.carModel + sharedProperties.carMake; }); 

我想通过指出推荐的方式来分享控制器之间的数据,甚至指令是通过使用服务(工厂),因为它已经指出,但我也想提供一个如何做到这一点应该做的工作的实际例子。

这里是工作plunker: http ://plnkr.co/edit/Q1VdKJP2tpvqqJL1LF6m?p=info

首先, 创build你的服务 ,这将有你的共享数据

 app.factory('SharedService', function() { return { sharedObject: { value: '', value2: '' } }; }); 

然后,只需将其注入到控制器中 ,然后在您的示波器上获取共享数据:

 app.controller('FirstCtrl', function($scope, SharedService) { $scope.model = SharedService.sharedObject; }); app.controller('SecondCtrl', function($scope, SharedService) { $scope.model = SharedService.sharedObject; }); app.controller('MainCtrl', function($scope, SharedService) { $scope.model = SharedService.sharedObject; }); 

你也可以这样做你的指令 ,它的工作原理是一样的:

 app.directive('myDirective',['SharedService', function(SharedService){ return{ restrict: 'E', link: function(scope){ scope.model = SharedService.sharedObject; }, template: '<div><input type="text" ng-model="model.value"/></div>' } }]); 

希望这个实用而干净的答案对某人有所帮助。

以下示例显示如何在兄弟控制器之间传递variables, 在值更改时执行操作。

用例示例:在侧栏中有一个filter,用于更改另一个视图的内容。

 angular.module('myApp', []) .factory('MyService', function() { // private var value = 0; // public return { getValue: function() { return value; }, setValue: function(val) { value = val; } }; }) .controller('Ctrl1', function($scope, $rootScope, MyService) { $scope.update = function() { MyService.setValue($scope.value); $rootScope.$broadcast('increment-value-event'); }; }) .controller('Ctrl2', function($scope, MyService) { $scope.value = MyService.getValue(); $scope.$on('increment-value-event', function() { $scope.value = MyService.getValue(); }); }); 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="myApp"> <h3>Controller 1 Scope</h3> <div ng-controller="Ctrl1"> <input type="text" ng-model="value"/> <button ng-click="update()">Update</button> </div> <hr> <h3>Controller 2 Scope</h3> <div ng-controller="Ctrl2"> Value: {{ value }} </div> </div> 

你不能让属性作为范围父项的一部分吗?

 $scope.$parent.property = somevalue; 

我不是说这是对的,但它的工作原理。

嗯,有一些这个新的东西作为另一种select。 这是本地存储,在有angular度的地方工作。 别客气。 (但是真的,谢谢那个家伙)

https://github.com/gsklee/ngStorage

定义你的默认值:

 $scope.$storage = $localStorage.$default({ prop1: 'First', prop2: 'Second' }); 

访问值:

 $scope.prop1 = $localStorage.prop1; $scope.prop2 = $localStorage.prop2; 

存储值

 $localStorage.prop1 = $scope.prop1; $localStorage.prop2 = $scope.prop2; 

请记住在您的应用程序中注入ngStorage,并在控制器中注入$ localStorage。

有两种方法可以做到这一点

1)使用get / set服务

2) $scope.$emit('key', {data: value}); //to set the value $scope.$emit('key', {data: value}); //to set the value

  $rootScope.$on('key', function (event, data) {}); // to get the value 

你可以用服务或工厂来做到这一点。 除了一些核心差异之外,它们本质上是相同的。 我发现thinkster.io的这个解释是最容易遵循的。 简单,重要,有效。

第二种方法:

 angular.module('myApp', []) .controller('Ctrl1', ['$scope', function($scope) { $scope.prop1 = "First"; $scope.clickFunction = function() { $scope.$broadcast('update_Ctrl2_controller', $scope.prop1); }; } ]) .controller('Ctrl2', ['$scope', function($scope) { $scope.prop2 = "Second"; $scope.$on("update_Ctrl2_controller", function(event, prop) { $scope.prop = prop; $scope.both = prop + $scope.prop2; }); } ]) 

Html:

 <div ng-controller="Ctrl2"> <p>{{both}}</p> </div> <button ng-click="clickFunction()">Click</button> 

欲了解更多信息,请参阅plunker:

http://plnkr.co/edit/cKVsPcfs1A1Wwlud2jtO?p=preview

如果你不想提供服务,那么你可以这样做。

 var scope = angular.element("#another ctrl scope element id.").scope(); scope.plean_assign = some_value; 

除了$ rootScope和services之外,还有一个干净而简单的替代解决scheme来扩展angular来添加共享数据:

在控制器中:

 angular.sharedProperties = angular.sharedProperties || angular.extend(the-properties-objects); 

此属性属于“angular度”对象,与范围分开,可在范围和服务中共享。

它的一个好处是你不必注入对象:它们在你定义后立即可以随时访问!