我有两个控制器和一个共享服务。控制器A是页面的主视图,包含填充数据的ng-repeat
。控制器B包含控制器A中ng-repeat
的过滤选项。这非常有效,并且我已经得到了一个基本的简化示例,说明了我在下面的工作方式。
我的问题是:如何在控制器A中引入更复杂的过滤?我知道我需要使用一个函数来进行复杂的过滤,这就是问题所在。
angular.module('app').factory('optionService', [/*'stuff'*/, options]);
function options(/*stuff*/){
var someOption = false;
var filters = {};
var service = {
someOption: someOption,
filters: filters
}
return service;
}
angular.module('app').controller('controllera', ['dataSvc', 'optionService', ctrla]);
function ctrla(dataSvc, optionService){
var vm = this;
vm.options = optionService;
vm.items = dataSvc.getItems();
}
angular.module('app').controller('controllerb', ['optionService', ctrlb]);
function ctrlb(optionService){
var vm = this;
vm.options = optionService;
vm.toggleSomeOption = function(){
vm.options.someOption = !vm.options.someOption;
if(vm.options.someOption){
vm.options.filters.someProperty = 'foo';
} else {
delete vm.options.filters['someProperty'];
}
}
}
<div ng-controller="controllera as vm">
<ul>
<li ng-repeat="item in vm.items | filter:vm.options.filters">{{item.bar}}</li>
</ul>
</div>
我已尝试将过滤方法添加到服务中,并将其作为过滤器添加到ng-repeat
中,但在更新选项时不会触发。
我是否应该使用事件或$rootScope
以某种方式通知controllera控制器b中的选项已更改并且需要更新(例如通过手动注入自定义过滤器并运行它)?
总而言之,我对如何使这项工作感到困惑,并采取最佳方法。
答案 0 :(得分:1)
是的,我认为更新没有发生,因为当ControllerB的范围发生变化但angular不知道它应该检查ControllerA的范围时。
你可以开始搞乱$scope.$digest()
或$timeout(func, 0)
,但它们非常难看,远非“最佳实践”。我宁愿建议使用$timeout()
,因为这也会导致对范围进行脏检查。所以这个过程:
$timeout()
。这样它的范围就会知道变化pull-right
立即执行并更新ControllerA的范围答案 1 :(得分:0)
我已设法使用$rootScope.$broadcast
和$scope.$on
实现此目的。
在控制器B中,当选择该选项时(它是checkbox
),我切换存储在服务中的选项,并广播事件以说明选项已更新。在控制器A中,监听事件,并且作为依赖项传入的过滤器被应用并针对复杂的过滤器方法运行,该过滤器方法只是一堆if / elses(虽然这将很快被重构到其他地方) )。
angular.module('app').factory('optionService', [/*'stuff'*/, options]);
function options(/*stuff*/){
var someOption = false;
var service = {
someOption: someOption
}
return service;
}
angular.module('app').controller('controllera', ['dataSvc', '$scope', 'filterFilter', 'optionService', ctrla]);
function ctrla(dataSvc, optionService){
var vm = this;
vm.options = optionService;
vm.items = dataSvc.getItems();
vm.filtereditems = [];
function complexFilter(item){
if(item.foo === 'bar' && vm.options.someOption){
return true;
}
/* etc etc */
}
function runFilter(){
vm.filtereditems = filterFilter(vm.items, complexFilter);
}
$scope.$on('updated', function(){
runFilter();
};
}
angular.module('app').controller('controllerb', ['optionService', '$rootScope', ctrlb]);
function ctrlb(optionService, $rootScope){
var vm = this;
vm.options = optionService;
vm.toggleSomeOption = function(){
vm.options.someOption = !vm.options.someOption;
$rootScope.$broadcast('updated');
}
}
<div ng-controller="controllera as vm">
<ul>
<li ng-repeat="item in vm.filtereditems">{{item.bar}}</li>
</ul>
</div>