我有大约四个主要的相关指令对,同时显示在我的AngularJS UI中。一般来说,每一对包括与它下方的相关联的细节编辑指令顶部的父列表指令,如该图所示:Angular中的兄弟指令/控制器相关列表(和主/细节)
每个右侧列表具有多到一个与关系必须始终显示激活的左侧选择和相关数据。 我应该如何驱动相关列表(从左到右的关联)刷新?
目前,每个主从指令对,或者“堆叠”,共享服务。该服务包含itemState.active
(活动详细记录)和itemState.headers
(查询主结果列表)。主控面板或详细面板中的活动调用服务,这直接影响服务状态。然后,在这个共同的positionService.state
上通过简单的声明式Angular手表来操作主/细节关联;几乎不需要控制器代码。我希望在这里使用服务作为单一事实点将使我能够轻松地将未来的近实时显示进行集成,例如通过SignalR
。这个主 - 细节实现仅在这里提供用于背景,但我欢迎改进:
主指令,例如, position-list.js
templateUrl: "position/position-list.html",
controller: ['$scope', 'positionSvc', function ($scope, positionService) {
$scope.positions = positionService.itemState();
$scope.select = function (position) {
positionService.read(position.id)
};
}
主模板,例如position-list.html
<li ng-repeat="i in itemState.headers" ng-click="select(i)">{{i.title}}</li>
服务,例如position-svc.js
this.itemState = {
headers: [],
active: { id: 0 },
pending: httpSvc.pending
};
this.create = function (detail) {
httpSvc.remote("post", detail).then(function (header) {
itemState.headers.unshift(header);
read(detail.id);
});
}
this.read = function (id) {
httpSvc.remote("get", id).then(function (detail) {
itemState.active = detail;
});
}
类似的指令和模板存在的细节。它共享相同的服务。你明白了。
现在我正在寻找一种可维护的方式来处理这种左右事件,遵循良好的设计实践和众所周知的AngularJS模式。我想保留我的指令的可组合性。
为了证明我不是在找你做我的工作,我(和整理我自己的想法),这里是我想出了一些办法,但没有一个似乎正确为止。我将继续记录这些内容,请检查是否需要清理此部分。它们是通过消息路径分组:
- leftController - > mainApp - > rightController
- 部分:leftController - > mainApp
mainApp.$scope.onLeftItemSelected
(例如,经由{ scope: '&' }
)leftController.$scope.$emit
内leftController.watch
leftController.$parent.onLeftItemSelected
(例如AngularJS access parent scope from child controller,但错误地创建自下而上依赖性)
- 部分b:mainApp - > rightController
mainApp.$scope.$broadcast
mainApp.rightService.load(leftItemId)
- 部分:leftController - > mainApp
- leftController - > mainApp模型 - > rightController $ watch
- 在leftController和rightController之间共享父范围变量
- 使用
{ scope: '=' }
将隔离范围从leftController传输到mainApp;这就是耶稣金塔纳的解决方案,下面,在这里:http://plnkr.co/edit/tyZPziT9VoWDFqHdF8A5?p=preview
- leftController - > $路径 - > rightController
- 实施,这可能是理想的,让我提供深层链接/书签到我的单页面应用程序,但需要在选择子项时启用页面加载父层次结构,而不仅仅是相反(加载所选父项的子记录)。这需要比我目前可以证明的更大的初始投资。 http://embed.plnkr.co/DBSbiV/preview
- leftService - > rightService
- 注入
nominationService
也进兄弟positionService
。设置positionService.activeRecord
时请致电nominationService.load(positionid)
。 Pro:已经在工作。 Con:错了。这种兄弟依赖关系使父列表不可用。 - 添加自定义的发布/订阅服务(https://stackoverflow.com/questions/16235689#16235822,http://jsfiddle.net/ThomasBurleson/sv7D5/)
- 注入
- leftService - > $ rootScope.broadcast - > rightService
- 不理想,假设我们的事件字符串将在根命名空间独特(但性能问题已经得到解决,这里https://stackoverflow.com/questions/11252780#19498009讨论)
- leftService - > mainApp - > rightService
- 将
positionService
和nominationService
注入mainApp
。向positionService
添加一个简单的事件列表以向上传送通知。 PRO:这保留了leftService的角色,作为整个应用程序中活动记录的单一事实点(如Martin Cortez在下面评论中所述)
- 将
- leftService - > $ rootScope。$路径 - > rightController - > rightService
- 看笔记方法3
参考 pass data between controllers How to communicate between controllers while not using SharedService between them?
我喜欢6号最好的。它似乎符合您最小化控制器代码的目标(改为强调服务)。它还维护您已经创建的组织。沿着这条线,可能类似于保留在事件列表中的“leftToRightService(leftService,rightService)”。如果你允许它接受和执行一个作为参数提供的函数,'leftToRightService'可能是可重用的。 – 2014-10-17 23:30:23
@MartinCortez:+1,谢谢。我在这之间做出了决定(它保留了更多的“单一事实点”),以及下面JesúsQuintana提供的解决方案(这可能是大多数角色开发人员所期望的)。 – shannon 2014-10-18 06:33:17