如何在控制器之间传递变量?

我有两个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中使用Ctrl1,因为它是未定义的。然而,如果我试图像这样传递它。

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();

也失败了。

这些控制器彼此之间不是嵌套的。

332995 次浏览

跨多个控制器共享变量的一种方法是创建服务并将其注入到你想要使用它的任何控制器中。

简单的服务示例:

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课)。

我发现,如果你想跨多个控制器绑定到这些属性,如果你绑定到一个对象的属性而不是一个基本类型(布尔值,字符串,数字)来保留绑定引用,效果会更好。

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


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

  • 绑定到共享值的静态副本(在myController1中)
    • 绑定到原语(字符串)
    • 绑定到对象的属性(保存到作用域变量)
    • 李< / ul > < / >
    • 绑定到共享值,当值更新时更新UI(在myController2中)
      • 绑定到返回原语(字符串)的函数
      • 绑定到对象的属性
      • 对对象属性的双向绑定
      • 李< / ul > < / >

如果你不想做服务,你可以这样做。

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

难道不能让属性也成为作用域父对象的一部分吗?

$scope.$parent.property = somevalue;

我不是说它是对的,但它确实有效。

—我知道这个答案不适合这个问题,但我希望阅读这个问题并希望处理工厂等服务的人避免这样做的麻烦----

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

服务是最佳实践,用于在非嵌套控制器之间共享数据。

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

我从“ng-book: the complete book on AngularJS”中读到,AngularJS的ng-models在控制器中创建为裸数据是错误的!

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

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';
};
});

这是因为DOM(html文档)建议(最佳实践)将调用包含为

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

这对于嵌套控制器非常有用,如果你想让你的子控制器能够从父控制器....改变一个对象

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

假设你有一个服务“Factory”,在返回空间中有一个objectA,它包含objectB, objectB又包含objectC。

如果你想从你的控制器GET对象tc到你的作用域,这样说是错误的:

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

那不会起作用…

$scope.neededObjectInController = Factory.ObjectA;

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

你可以在服务业或工厂里这样做。除了一些核心差异外,它们本质上是一样的。我发现thinkster.io上的这个解释是最容易理解的。简单、扼要、有效。

上面的示例非常有效。我只是做了一个修改,以防我需要管理多个值。我希望这能有所帮助!

app.service('sharedProperties', function () {


var hashtable = {};


return {
setValue: function (key, value) {
hashtable[key] = value;
},
getValue: function (key) {
return hashtable[key];
}
}
});

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

下面是一个非常简单的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


如果这太简单,这里有一个更复杂的例子

在这里查看相关最佳实践评论的答案

不创建服务的解决方案,使用$rootScope:

要跨应用控制器共享属性,你可以使用Angular $rootScope。这是共享数据的另一种选择,让人们知道它。

在控制器之间共享一些功能的首选方式是服务,读取或更改全局属性可以使用$rootscope。

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>

啊,吃点这种新东西作为另一种选择。它是本地存储,在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。

我想通过指出在控制器之间甚至指令之间共享数据的推荐方式是使用服务(工厂)来回答这个问题,正如已经指出的那样,但我也想提供一个工作的实际示例,说明应该如何做到这一点。

下面是工作活塞: http://plnkr.co/edit/Q1VdKJP2tpvqqJL1LF6m?p=info

首先,创建你的服务,它将包含你的共享数据:

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>'
}
}]);

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

除了$rootScope和services,还有一个干净简单的解决方案来扩展angular来添加共享数据:

在控制器中:

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

该属性属于'angular'对象,与作用域分离,可以在作用域和服务中共享。

它的一个好处是你不需要注入对象:它们可以在你定义后的任何地方立即访问!

有两种方法

1)使用get/set服务

< p > 2) $scope.$emit('key', {data: value}); //to set the value < / p >
 $rootScope.$on('key', function (event, data) {}); // to get the value

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

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;


});

第二种方法:

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;
});
}
])

< p > Html:

<div ng-controller="Ctrl2">
<p>\{\{both}}</p>
</div>


<button ng-click="clickFunction()">Click</button>

欲了解更多细节,请参阅plunker:

< a href = " http://plnkr.co/edit/cKVsPcfs1A1Wwlud2jtO?p =预览”rel = " nofollow”> http://plnkr.co/edit/cKVsPcfs1A1Wwlud2jtO?p =预览< / >

下面的例子展示了如何在兄弟姐妹控制器之间传递变量。

用例示例:在侧栏中有一个过滤器,可以更改另一个视图的内容。

.
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>

我看了上面的答案,我推荐pejman在16年12月29日13:31的建议,但他/她没有留下完整的答案。在这里,我把它写成>(你需要一个服务和一个监听器看美元在控制器的作用域上来改变服务区域)

var app =
angular.module('myApp', ['ngRoute', 'ngSanitize']);


app.service('bridgeService', function () {
var msg = "";
return msg;
});
app.controller('CTRL_1'
, function ($scope, $http, bridgeService)
{
$http.get(_restApi, config)
.success(
function (serverdata, status, config) {
$scope.scope1Box = bridgeService.msg = serverdata;
});
});
app.controller('CTRL_2'
, function ($scope, $http, bridgeService)
{
$scope.$watch( function () {
return (bridgeService.msg);
}, function (newVal, oldVal) {
$scope.scope2Box = newVal;
}, true
);
});