Un contrôleur AngularJS peut-il hériter d'un autre contrôleur dans le même module?

dans un module, un contrôleur peut hériter des propriétés d'un contrôleur extérieur:

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

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

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

exemple via: lien mort : http://blog.omkarpatil.com/2013/02/controller-inheritance-in-angularjs.html

Peut aussi un contrôleur à l'intérieur d'un module d'hériter d'un frère?

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

le deuxième code ne fonctionne pas depuis $injector.invoke nécessite une fonction comme premier paramètre et ne trouve pas la référence à ParentCtrl .

194
demandé sur Claies 2013-08-27 13:03:37

10 réponses

Oui, il peut, mais vous devez utiliser le service $controller pour instancier le contrôleur à la place: -

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
});
281
répondu Salman Abbas 2016-12-06 18:47:30

dans le cas où vous utilisez vm syntaxe du contrôleur , voici ma solution:

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

malheureusement, vous ne pouvez pas utiliser $controller.call(vm, 'BaseGenericCtrl'...) , pour passer le contexte actuel dans la fonction de fermeture (pour reload() ), donc une seule solution est d'utiliser this dans la fonction héritée afin de changer dynamiquement le contexte.

19
répondu IProblemFactory 2015-12-06 02:05:49

je pense,vous devriez utiliser l'usine ou le service,pour donner des fonctions accessibles ou des données pour les deux contrôleurs.

voici une question similaire - - - > AngularJS contrôleur héritage

8
répondu LauroSkr 2017-05-23 12:26:10

en réponse à la question soulevée dans cette réponse de gmontague , j'ai trouvé une méthode pour hériter un controller en utilisant $controller(), et toujours utiliser le controller" as " syntaxe.

tout D'abord, utilisez "comme" syntaxe lorsque vous héritez appelant $controller ():

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

    });

puis, dans le modèle HTML, si la propriété est définie par parent, puis utiliser parent. pour récupérer les propriétés héritées de parent; si défini par enfant, puis utilisez child. pour le récupérer.

    <div ng-controller="ChildCtrl as child">{{ parent.foo }}</div>
7
répondu gm2008 2017-05-23 12:34:27

J'ai fait ça d'une autre manière. Dans mon cas, je voulais une fonction qui appliquent les mêmes fonctions et les propriétés dans d'autres contrôleurs. J'ai bien aimé, sauf par des paramètres. De cette façon, tous vos enfants ont besoin de recevoir $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();
});
4
répondu Fabio Montefuscolo 2015-09-25 13:22:01

pour ceux qui se demandent, vous pouvez étendre les contrôleurs de composants de la même manière, en utilisant la méthode dans la réponse acceptée.

utiliser l'approche suivante:

composant Parent (à étendre de):

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

composant enfant (le seul s'étendant):

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

le truc est d'utiliser des contrôleurs nommés, au lieu de les définir dans la définition du composant.

3
répondu Adam Reis 2017-01-24 23:10:18

comme mentionné dans la réponse acceptée, vous pouvez" hériter "des modifications d'un contrôleur parent à $scope et autres services en appelant: $controller('ParentCtrl', {$scope: $scope, etc: etc}); dans votre contrôleur enfant.

Toutefois , il échoue si vous êtes habitué à l'utilisation de la manette " a " de la syntaxe, par exemple dans

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

si foo a été défini dans le contrôleur parent (via this.foo = ... ), le contrôleur enfant n'y aura pas accès.

comme mentionné dans les commentaires, vous pouvez attribuer le résultat de $controller directement à la portée:

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

Note: vous alors devez supprimer la partie " as " de ng-controller= , parce que vous spécifiez le nom de l'instance dans le code, et non plus le modèle.

2
répondu gmontague 2015-06-19 21:03:58

j'utilisais la syntaxe" Controller as "avec vm = this et je voulais hériter d'un controller. J'avais des problèmes si mon contrôleur parent avait une fonction qui modifiait une variable.

à l'Aide IProblemFactory et Salman Abbas des réponses, je n'ai la suite d'avoir accès à des variables parents:

(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
répondu dufaux 2017-07-14 19:58:35

vous pouvez utiliser un mécanisme D'héritage JavaScript simple. Aussi, n'oubliez pas de passer des services tout à fait angulaires à invoquer de .appel de la méthode.

//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
répondu trueboroda 2017-04-05 10:08:20

Désignent ci-après le lien pour AngularJs inheritences feartue.

Contrôleur-l'Héritage-en-angularjs

0
répondu Sheo Dayal Singh 2018-01-28 17:21:43