AngularJS控制器能否从同一模块中的另一个控制器inheritance?

在模块中,控制器可以inheritance外部控制器的属性:

var app = angular.module('angularjs-starter', []); var ParentCtrl = function ($scope, $location) { }; app.controller('ChildCtrl', function($scope, $injector) { $injector.invoke(ParentCtrl, this, {$scope: $scope}); }); 

示例通过: 无效链接http : //blog.omkarpatil.com/2013/02/controller-inheritance-in-angularjs.html

一个模块中的控制器也可以inheritance兄弟吗?

 var app = angular.module('angularjs-starter', []); app.controller('ParentCtrl ', function($scope) { //I'm the sibling, but want to act as parent }); app.controller('ChildCtrl', function($scope, $injector) { $injector.invoke(ParentCtrl, this, {$scope: $scope}); //This does not work }); 

第二个代码不起作用,因为$injector.invoke需要一个函数作为第一个参数,并且没有find对ParentCtrl的引用。

是的,它可以但你必须使用$controller服务实例化控制器: –

 var app = angular.module('angularjs-starter', []); app.controller('ParentCtrl', function($scope) { // I'm the sibling, but want to act as parent }); app.controller('ChildCtrl', function($scope, $controller) { $controller('ParentCtrl', {$scope: $scope}); //This works }); 

如果你使用vm控制器的语法 ,这里是我的解决scheme:

 .controller("BaseGenericCtrl", function ($scope) { var vm = this; vm.reload = reload; vm.items = []; function reload() { // this function will come from child controller scope - RESTDataService.getItemsA this.getItems(); } }) .controller("ChildCtrl", function ($scope, $controller, RESTDataService) { var vm = this; vm.getItems = RESTDataService.getItemsA; angular.extend(vm, $controller('BaseGenericCtrl', {$scope: $scope})); }) 

不幸的是,你不能使用$controller.call(vm, 'BaseGenericCtrl'...)将当前上下文传递给closure(用于reload() )函数,因此只有一个解决scheme是使用this内部inheritance函数dynamic改变上下文。

我想,你应该使用工厂或服务,为两个控制器提供可访问的function或数据。

这里是类似的问题—> AngularJS控制器的inheritance

为了回应gmontague在这个答案中提出的问题,我find了一个使用$ controller()inheritance控制器的方法,并仍然使用控制器“as”语法。

首先,在inheritance调用$ controller()时使用“as”语法:

  app.controller('ParentCtrl', function(etc...) { this.foo = 'bar'; }); app.controller('ChildCtrl', function($scope, $controller, etc...) { var ctrl = $controller('ParentCtrl as parent', {etc: etc, ...}); angular.extend(this, ctrl); }); 

然后,在HTML模板中,如果属性由父项定义,则使用parent. 检索从父项inheritance的属性; 如果由孩子定义,那么使用child. 检索它。

  <div ng-controller="ChildCtrl as child">{{ parent.foo }}</div> 

那么,我用另一种方式做了这个。 在我的情况下,我想要一个function,在其他控制器应用相同的function和属性。 我喜欢它,除了参数。 这样,你所有的ChildCtrls都需要接收$ location。

 var app = angular.module('angularjs-starter', []); function BaseCtrl ($scope, $location) { $scope.myProp = 'Foo'; $scope.myMethod = function bar(){ /* do magic */ }; } app.controller('ChildCtrl', function($scope, $location) { BaseCtrl.call(this, $scope, $location); // it works $scope.myMethod(); }); 

正如在接受的答案中提到的,通过调用: $controller('ParentCtrl', {$scope: $scope, etc: etc}); ,可以“inheritance”父控制器对$ scope和其他服务的修改$controller('ParentCtrl', {$scope: $scope, etc: etc}); 在你的孩子控制器。

但是 ,如果您习惯于使用控制器“as”语法,例如,

 <div ng-controller="ChildCtrl as child">{{ child.foo }}</div> 

如果在父控制器中设置了foo (通过this.foo = ... ),子控制器将无法访问它。

正如在注释中提到的,您可以将$ controller的结果直接分配给作用域:

 var app = angular.module('angularjs-starter', []); app.controller('ParentCtrl ', function(etc...) { this.foo = 'bar'; }); app.controller('ChildCtrl', function($scope, $controller, etc...) { var inst = $controller('ParentCtrl', {etc: etc, ...}); // Perform extensions to inst inst.baz = inst.foo + " extended"; // Attach to the scope $scope.child = inst; }); 

注意:必须ng-controller=删除“as”部分,因为您要在代码中指定实例名称,而不再是模板。

对于那些想知道的,您可以使用接受的答案中的方法以相同的方式扩展组件控制器。

使用以下方法:

父组件(从中延伸):

 /** * Module definition and dependencies */ angular.module('App.Parent', []) /** * Component */ .component('parent', { templateUrl: 'parent.html', controller: 'ParentCtrl', }) /** * Controller */ .controller('ParentCtrl', function($parentDep) { //Get controller const $ctrl = this; /** * On init */ this.$onInit = function() { //Do stuff this.something = true; }; }); 

子组件(扩展的组件):

 /** * Module definition and dependencies */ angular.module('App.Child', []) /** * Component */ .component('child', { templateUrl: 'child.html', controller: 'ChildCtrl', }) /** * Controller */ .controller('ChildCtrl', function($controller) { //Get controllers const $ctrl = this; const $base = $controller('ParentCtrl', {}); //NOTE: no need to pass $parentDep in here, it is resolved automatically //if it's a global service/dependency //Extend angular.extend($ctrl, $base); /** * On init */ this.$onInit = function() { //Call parent init $base.$onInit.call(this); //Do other stuff this.somethingElse = true; }; }); 

诀窍是使用命名控制器,而不是在组件定义中定义它们。

我用vm = this的“Controller as”语法,想要inheritance一个控制器。 如果我的父控制器有一个修改variables的函数,我有问题。

使用IProblemFactory的和萨尔曼阿巴斯的答案,我做了以下访问父variables:

 (function () { 'use strict'; angular .module('MyApp',[]) .controller('AbstractController', AbstractController) .controller('ChildController', ChildController); function AbstractController(child) { var vm = child; vm.foo = 0; vm.addToFoo = function() { vm.foo+=1; } }; function ChildController($controller) { var vm = this; angular.extend(vm, $controller('AbstractController', {child: vm})); }; })(); 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-controller="ChildController as childCtrl" layout="column" ng-cloak="" ng-app="MyApp"> <button type="button" ng-click="childCtrl.addToFoo()"> add </button> <span> -- {{childCtrl.foo}} -- </span> </div> 

您可以使用简单的JavaScriptinheritance机制。 也不要忘记传递一个需要的angular度服务来调用.call方法。

 //simple function (js class) function baseCtrl($http, $scope, $location, $rootScope, $routeParams, $log, $timeout, $window, modalService) {//any serrvices and your 2 this.id = $routeParams.id; $scope.id = this.id; this.someFunc = function(){ $http.get("url?id="+this.id) .then(success function(response){ .... } ) } ... } angular .module('app') .controller('childCtrl', childCtrl); //angular controller function function childCtrl($http, $scope, $location, $rootScope, $routeParams, $log, $timeout, $window, modalService) { var ctrl = this; baseCtrl.call(this, $http, $scope, $location, $rootScope, $routeParams, $log, $timeout, $window, modalService); var idCopy = ctrl.id; if($scope.id == ctrl.id){//just for sample ctrl.someFunc(); } } //also you can copy prototype of the base controller childCtrl.prototype = Object.create(baseCtrl.prototype);