如何在控制器之间共享通用逻辑?

时间:2015-08-12 13:13:30

标签: javascript angularjs

我有两个页面和两个控制器,可以对同一个数据集执行搜索。一个有一个简单的表单来指定搜索条件。另一个允许用户在地图上选择数据(通过选择区域或点击地图上的要素)。

搜索结果显示在搜索控件下方的数据表上(在同一页面上)。

因此,控制器具有不同的搜索功能,但也有很多共同的行为,即从网格中显示网格,分页,重新加载,批量编辑数据等。

因此,在两个控制器中有几个重复的功能,有时会有轻微的变化,有时完全相同。

显示数据的页面部分也是一个共享模板,包含在$scope.selectAllRows = function(){ var selectedItems = $scope.searchState.selectedItems; angular.forEach($scope.searchState.searchResult.rows, function(row){ // add only if not already selected if(selectedItems.indexOf(row) < 0){ selectedItems.push(row); } }); }; 两个搜索页面上。

以下是一个例子:

ng-click

此函数选择表中的所有行。它绑定到页面上按钮的$scope

还有很多这样的功能,基本上从$scope读取一些状态,执行一些逻辑,然后将新的东西放回$scope

我想删除这些函数的重复,并在单个代码单元中重新组合常见行为。

注意:我在这里分享的是行为,而不是数据。这些函数将执行相同的逻辑,但在不同的范围内。

由于这些是真正的演示文稿/ UI内容,并且需要放在$scope上,我认为不能使用服务,因为myapp.defineCommonControllerBehaviour = function($scope, someOtherService){ $scope.selectAlRows = function(){....} $scope.someOtherCommonTask = function(){ someOtherService.doTheTask(); } //etc... }; //controller 1 myapp.defineCommonBehaviour($scope, someOtherService); //controller 2 myapp.defineCommonBehaviour($scope, someOtherService); 是一个严格控制器的东西,不能注入服务。

我正在尝试在另一个文件中定义独立函数,并从两个控制器调用此函数:

{{1}}

它有效,但不是很优雅,因为它在任何Angular模块之外的全局范围内定义了一个函数。

有没有一种有角度的原生方式来实现这一目标?或者至少更符合Angular架构?

2 个答案:

答案 0 :(得分:2)

我发现有一些模式对我的用例很有用。

neutral JS code可用于定义和继承您的控制器(缺少依赖关系管理和原型继承不会使它成为最佳选择,但ES2015类在这种情况下是一个很好的帮助。)

或者可以使用Angular依赖关系管理和store common methods and properties in a service

myApp.service('baseCtrl', function () {
  this.name = 'base';
  this.getName = function() {
    return this.name;
  };
});

myApp.controller('MainController', ['baseCtrl', function (baseCtrl) {
  angular.extend(this, baseCtrl);
  this.name = 'main';
}]);

有一些第三方解决方案,例如Classy,为控制器提供了自以为是的继承语法。

$injector$controller也可用于访问父控制器并继承它,但由于引入了controllerAs语法,因此无需弄乱$scope了。

答案 1 :(得分:0)

将常用功能放入commonCtrl的范围,并在子控制器中访问它们。 Angular child的scope继承自父母scope

<div ng-controller='commonCtrl'>
    <div ng-controller='featureOneCtrl'></div>
</div>
<div ng-controller='commonCtrl'>
    <div ng-controller='featureTwoCtrl'></div>
</div>