webentwicklung-frage-antwort-db.com.de

Kann ein AngularJS-Controller von einem anderen Controller im selben Modul erben?

Innerhalb eines Moduls kann ein Controller Eigenschaften von einem externen Controller erben:

var app = angular.module('angularjs-starter', []);

var ParentCtrl = function ($scope, $location) {
};

app.controller('ChildCtrl', function($scope, $injector) {
  $injector.invoke(ParentCtrl, this, {$scope: $scope});
});

Beispiel über: Dead linkhttp://blog.omkarpatil.com/2013/02/controller-inheritance-in-angularjs.html

Kann auch ein Controller in einem Modul von einem Geschwister erben?

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
});

Der zweite Code funktioniert nicht, da $injector.invoke eine Funktion als ersten Parameter benötigt und die Referenz auf ParentCtrl nicht gefunden wird.

195
Federico Elles

Ja, das kann, aber Sie müssen stattdessen den $controller-Dienst verwenden, um den Controller zu instanziieren: -

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
});
285
Salman Abbas

Falls Sie vm Controller-Syntax verwenden, ist hier meine Lösung:

.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}));
})

Leider können Sie $controller.call(vm, 'BaseGenericCtrl'...) nicht verwenden, um den aktuellen Kontext in die schließende Funktion (für reload()) zu übergeben. Daher können Sie this nur innerhalb der geerbten Funktion verwenden, um den Kontext dynamisch zu ändern.

19
IProblemFactory

Ich denke, Sie sollten Factory oder Service verwenden, um zugängliche Funktionen oder Daten für beide Steuerungen bereitzustellen.

hier ist ähnliche Frage ---> AngularJS Controller Vererbung

8
LauroSkr

Als Antwort auf das in diese Antwort von gmontague aufgeworfene Problem habe ich eine Methode gefunden, um einen Controller mithilfe von $ controller () zu erben, und benutze den Controller weiterhin als "Syntax". 

Verwenden Sie als erstes die Syntax "as", wenn Sie den Aufruf von $ controller () erben:

    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);

    });

Wenn die Eigenschaft in der HTML-Vorlage durch das übergeordnete Element definiert ist, verwenden Sie parent., um die vom übergeordneten Objekt geerbten Eigenschaften abzurufen. Wenn er von child definiert wurde, rufen Sie ihn mit child. ab. 

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

Nun, ich habe das anders gemacht. In meinem Fall wollte ich eine Funktion, die die gleichen Funktionen und Eigenschaften in anderen Steuerungen verwendet. Ich mochte es, außer bei Parametern. Auf diese Weise müssen alle ChildCtrls $ location erhalten.

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();
});
5

Für diejenigen, die sich fragen, können Sie Komponentencontroller auf dieselbe Weise erweitern, indem Sie die Methode in der akzeptierten Antwort verwenden. 

Verwenden Sie den folgenden Ansatz:

Übergeordnete Komponente (ausgehend von):

/**
 * 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;
  };
});

Kindkomponente (die Erweiterung):

/**
 * 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;
  };
});

Der Trick besteht darin, benannte Controller zu verwenden, anstatt sie in der Komponentendefinition zu definieren.

3
Adam Reis

Wie in der akzeptierten Antwort erwähnt, können Sie die Änderungen an $ scope und anderen Diensten eines übergeordneten Controllers "erben", indem Sie in Ihrem untergeordneten Controller Folgendes aufrufen: $controller('ParentCtrl', {$scope: $scope, etc: etc});.

Allerdings, schlägt dies fehl, wenn Sie es gewohnt sind, die Controller-as-Syntax zu verwenden, beispielsweise in

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

Wenn foo im übergeordneten Controller (über this.foo = ...) festgelegt wurde, hat der untergeordnete Controller keinen Zugriff darauf.

Wie in Kommentaren erwähnt, können Sie das Ergebnis von $ controller direkt dem Bereich zuordnen:

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;
});

Hinweis: Dann müssen Sie müssen den "as" -Part aus ng-controller= entfernen, da Sie den Instanznamen im Code und nicht mehr die Vorlage angeben.

2
gmontague

Ich verwendete die "Controller as" -Syntax mit vm = this und wollte einen Controller erben. Ich hatte Probleme, wenn mein übergeordneter Controller eine Funktion hatte, die eine Variable modifizierte.

Mit Hilfe der IProblemFactory und Salman Abbas - Antworten habe ich Folgendes getan, um Zugriff auf übergeordnete Variablen zu erhalten:

(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>

2
dufaux

Sie können einen einfachen JavaScript-Vererbungsmechanismus verwenden. Vergessen Sie auch nicht, einen notwendigerweise winkligen Service für den Aufruf der .call-Methode zu übergeben.

//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);
0
trueboroda

Siehe unten genannten Link für AngularJs Vererbung feartue.

Controller-Inheritance-in-anglejs

0