是否有可能让一个控制器使用另一个?
例如:
此HTML文档只是打印 MessageCtrl
文件中 MessageCtrl
控制器传递的消息 .
<html xmlns:ng="http://angularjs.org/">
<head>
<meta charset="utf-8" />
<title>Inter Controller Communication</title>
</head>
<body>
<div ng:controller="MessageCtrl">
<p>{{message}}</p>
</div>
<!-- Angular Scripts -->
<script src="http://code.angularjs.org/angular-0.9.19.js" ng:autobind></script>
<script src="js/messageCtrl.js" type="text/javascript"></script>
</body>
</html>
控制器文件包含以下代码:
function MessageCtrl()
{
this.message = function() {
return "The current date is: " + new Date().toString();
};
}
这只是打印当前日期;
如果我要添加另一个控制器 DateCtrl
,它将日期以特定格式交回 MessageCtrl
,那怎么会这样做呢? DI框架似乎与 XmlHttpRequests
和访问服务有关 .
13 回答
实际上使用发射和广播是低效的,因为事件在范围层次结构中上下波动,这很容易降级为复杂应用程序的性能瓶装 .
我建议使用服务 . 以下是我最近在我的一个项目中实现它的方法 - https://gist.github.com/3384419 .
基本思路 - 将pub-sub / event总线注册为服务 . 然后在需要订阅或发布事件/主题的地方注入该事件总线 .
在角度1.5中,这可以通过执行以下操作来完成:
这是父组件 . 在这里我创建了一个函数,将另一个对象推入我的
productForms
数组 - 注意 - 这只是我的例子,这个函数可以是真正的 .现在我们可以创建另一个将使用
require
的组件:这里子组件正在创建对父组件函数
addNewForm
的引用,然后可以将其绑定到HTML并像其他任何函数一样调用 .以下是
publish-subscribe
方法,与Angular JS无关 .Search Param Controller
Search Choices Controller
Event Manager
Global
我也知道这种方式 .
但是我没有太多使用它,因为我不喜欢在角度代码中使用jQuery选择器 .
以下是两个控制器共享服务数据的一页示例:
也在这里:https://gist.github.com/3595424
有一种方法不依赖于服务,
$broadcast
或$emit
. 它并不适用于所有情况,但如果您有2个可以抽象为指令的相关控制器,那么您可以在指令定义中使用require
选项 . 这很可能是ngModel和ngForm之间的沟通方式 . 您可以使用它在嵌套的指令控制器之间或在同一元素上进行通信 .对于父母/子女情况,使用方法如下:
让它工作的要点:在父指令上,使用要调用的方法,你应该在
this
上定义它们(不在$scope
上):在子指令定义中,您可以使用
require
选项,以便将父控制器传递给链接函数(这样您就可以从子指令的scope
调用函数) .上面的内容可以在http://plnkr.co/edit/poeq460VmQER8Gl9w8Oz?p=preview看到
类似地使用兄弟指令,但两个指令在同一元素上:
通过在
directive1
上创建方法来使用:在directive2中,可以使用
require
选项调用它,这会导致siblingController传递给链接函数:这可以在http://plnkr.co/edit/MUD2snf9zvadfnDXq85w?p=preview看到 .
这个的用途?
Parent:子元素需要与父级“注册”的任何情况 . 很像ngModel和ngForm之间的关系 . 这些可能会添加某些可能影响模型的行为 . 你可能也有纯粹基于DOM的东西,其中父元素需要管理某些孩子的位置,比如管理或反应滚动 .
兄弟姐妹:允许指令修改其行为 . ngModel是经典案例,用于在输入上添加解析器/验证到ngModel使用 .
看到这个小提琴:http://jsfiddle.net/simpulton/XqDxG/
另请观看以下视频:Communicating Between Controllers
HTML:
JavaScript的:
您可以在父控制器(MessageCtrl)中注入'$controller'服务,然后使用以下命令实例化/注入子控制器(DateCtrl):
$scope.childController = $controller('childController', { $scope: $scope.$new() });
现在,您可以通过调用其方法来访问子控制器中的数据,因为它是一项服务 .
如果有任何问题,请告诉我 .
另外两个小提琴:(非服务方式)
1)对于Parent-Child控制器 - 使用父控制器的
$scope
发出/广播事件 . http://jsfiddle.net/laan_sachin/jnj6y/2)在非相关控制器上使用
$rootScope
. http://jsfiddle.net/VxafF/如果要将一个控制器调用另一个控制器,则有四种方法可用
$ rootScope . $ emit()和$ rootScope . $ broadcast()
如果第二个控制器是子控制器,则可以使用父子通信 .
使用服务
一种黑客攻击 - 在angular.element()的帮助下
控制器及其范围可能会被破坏,但$ rootScope仍然在整个应用程序中,这就是为什么我们要使用$ rootScope,因为$ rootScope是所有范围的父级 .
如果您正在进行从父母到孩子的沟通,甚至孩子都想要与兄弟姐妹沟通,你可以使用$ broadcast
如果您正在从孩子到父母进行通信,那么没有兄弟姐妹进行调用,那么您可以使用$ rootScope . $ emit
HTML
Angularjs代码
在$ emit'childEmit'的上面代码控制台中不会调用子兄弟姐妹内部,它只调用父内部,其中$ broadcast也会在兄弟姐妹和父母内部调用 . 这是性能进入行动的地方 . $ emit是如果您使用子到父母的沟通,因为它会跳过一些脏检查,这是可取的 .
它是最好的方法之一,如果你想做 child parent communication ,孩子想要与 immediate parent 沟通,那么它不需要任何类型的$ broadcast或$ emit但是如果你想从父母到孩子进行沟通,那么你必须使用任何一种服务或$广播
例如HTML: -
Angularjs
无论何时使用子到父进程通信,Angularjs都会在子进程内搜索变量,如果内部不存在变量,那么它将选择查看父控制器内的值 .
AngularJS支持使用服务体系结构的"Seperation of Concerns"的概念 . 服务是javascript函数,只负责执行特定任务 . 这使得它们成为 individual entity ,这是用于使用Angularjs的依赖注入mecahnism注入的服务 .
Angularjs代码:
它将输出Hello Child World和Hello Parent World . 根据Angular docs of services Singletons - 依赖于服务的每个组件都获得对服务工厂生成的单个实例的引用 .
这个方法从元素中获取scope()的Id / unique class.angular.element()方法返回元素,scope()给另一个变量的$ scope变量使用另一个控制器的$ scope变量,这不是一个好习惯 .
HTML: -
Angularjs: -
在上面的代码控制器在Html上显示它们自己的值,当你点击文本时,你将相应地在控制台中获得值 . 如果你点击父控制器 Span ,浏览器将控制子的值,反之亦然 .
If you are looking to emit & broadcast events to share data or call functions across controllers ,请查看link:并通过
zbynour
检查答案(以最大票数回答) . 我在引用他的答案!!!If scope of firstCtrl is parent of the secondCtrl scope, your code should work by replacing $emit by $broadcast in firstCtrl:
In case there is no parent-child relation between your scopes you can inject $rootScope into the controller and broadcast the event to all child scopes (i.e. also secondCtrl).
Finally, when you need to dispatch the event from child controller to scopes upwards you can use $scope.$emit. If scope of firstCtrl is parent of the secondCtrl scope:
如何在控制器之间进行通信有多种方法 .
最好的可能是共享服务:
另一种方法是在范围上发出事件:
在这两种情况下,您也可以与任何指令进行通信 .
我不知道这是否超出标准,但如果您将所有控制器放在同一个文件中,那么您可以执行以下操作:
正如您所看到的,在调用updateCharts时,indicatorsCtrl正在调用另一个控制器的updateChart函数 .