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:
如果你不想提供服务,那么你可以这样做。
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度”对象,与范围分开,可在范围和服务中共享。
它的一个好处是你不必注入对象:它们在你定义后立即可以随时访问!