क्या एक AngularJS कंट्रोलर उसी मॉड्यूल में किसी अन्य कंट्रोलर से इनहेरिट कर सकता है?


198

एक मॉड्यूल के भीतर, एक नियंत्रक बाहर के नियंत्रक से गुण प्राप्त कर सकता है:

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-angkarjs.html

एक मॉड्यूल के अंदर एक नियंत्रक भी एक भाई से विरासत में मिल सकता है?

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पहले पैरामीटर के रूप में फ़ंक्शन की आवश्यकता होती है और इसका संदर्भ नहीं मिलता है ParentCtrl


यह मदद करनी चाहिए: stackoverflow.com/questions/16828287/…
बार्ट

2
एक तरफ: यह विरासत की तरह नहीं दिखता है, लेकिन साझा करने के तरीकों या इंजेक्शन लगाने की तरह अधिक है। शायद सिर्फ शब्दार्थ।
alockwood05

उदाहरण के लिए लिंक अब मान्य नहीं है।
एलेक्स्स

Google Cache लिंक: webcache.googleusercontent.com/… जो इस दिलचस्प अंक की ओर इशारा करता है: jsfiddle.net/mhevery/u6s88/12
Federico Elles

जवाबों:


289

हां, इसके $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
});

ParentCtrlहोना चाहिए controllerया एक का उपयोग करना संभव है service?
मारुत 6'14

@gontard: इस मामले में यह एक नियंत्रक होना चाहिए, क्योंकि $controllerकेवल पंजीकृत नियंत्रक का उपयोग कर सकते हैं।
जीसस

10
यह बहुत अच्छा उपाय है। धन्यवाद। लेकिन अगर मैं नियंत्रक सिंटैक्स का उपयोग कर रहा हूं तो मैं इसे कैसे करूंगा?
का

1
उपरोक्त फिडेल को एक प्रश्न के रूप में पूछा गया था। यह कि controllerAs ध्यान देने योग्य बात बस लायक गुंजाइश के लिए नियंत्रक प्रदान करती है - तो क्या आप बदल जाएगा $scopeकरने के लिए this(सिद्धांत में)
दान पेंट्री

4
यह मेरे लिए काम करता है, हालांकि मैं इसे इस तरह से करने की कोशिश कर रहा हूं कि मेरे पास एक ही पृष्ठ पर अभिभावक नियंत्रक और बाल नियंत्रक हैं। यह पैरेंट कंट्रोलर में $ http ऑपरेशन को दो बार चलाने का कारण बनता है। जब चाइल्ड कंट्रोलर पेरेंट कंट्रोलर के स्कोप को मेरे $ स्कोप में इंजेक्ट करता है। सभी मेमर्स एरे को दो बार पॉप्युलेट करते हैं क्योंकि पेरेंट कंट्रोलर इसे चलाने का कारण बनता है, तो चाइल्ड कंट्रोलर इसे फिर से चलाने का कारण बनता है। क्या इससे बचाव का कोई तरीका है?
रयान मान

20

यदि आप vmनियंत्रक सिंटैक्स का उपयोग कर रहे हैं , तो यहां मेरा समाधान है:

.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'...)वर्तमान संदर्भ को क्लोजर (फॉर reload()) फ़ंक्शन में पास करने के लिए उपयोग नहीं कर सकते हैं , इसलिए thisडायनेमिक रूप से संदर्भ को बदलने के लिए विरासत में दिए गए फ़ंक्शन के अंदर केवल एक समाधान का उपयोग करना है।


क्या आप इसके बजाय बस ऐसा नहीं कर सकते थे? > $ नियंत्रक ('बेसगेनिककंट्रोल', {vm: vm});
हेरिंगटाउन

vmनियंत्रक के अंदर एक चर है, मुझे नहीं लगता कि एंगुलर उम्मीद के मुताबिक इसका इस्तेमाल कर सकता है।
IProblemFactory

8

मुझे लगता है, आपको दोनों नियंत्रकों के लिए सुलभ कार्यों या डेटा देने के लिए, कारखाने या सेवा का उपयोग करना चाहिए।

यहाँ इसी तरह का सवाल है ---> AngularJS नियंत्रक विरासत


हाँ, यह एक तरीका है, धन्यवाद। मैं उस पद पर आया था जब मैं समाधान खोज रहा था। मैं सोच रहा था कि क्या नियंत्रक फ़ंक्शन को लोड करने और इसके साथ "इस" का विस्तार करने का कोई तरीका था।
को

मैं एक सार्वभौमिक loadingचर रखना चाहूंगा ताकि जब डेटा लोड हो रहा हो तो मैं हमेशा वही काम करता हूं, मुझे नहीं लगता कि कारखाने ऐसा कर सकते हैं। मेरे माता-पिता नियंत्रक का लोडिंग वैरिएबल हो सकता है लेकिन फैक्ट्री इसमें हेरफेर नहीं कर सकती ... ठीक है ?!
PixMach

7

इस जवाब में गिम्मेग द्वारा उठाए गए मुद्दे के जवाब में , मुझे $ नियंत्रक () का उपयोग करके एक नियंत्रक को विरासत में प्राप्त करने का एक तरीका मिला है, और अभी भी "सिंटैक्स" के रूप में नियंत्रक का उपयोग करें।

सबसे पहले, जब आप $ कंट्रोलर () कॉलिंग प्राप्त करते हैं तो "सिंटैक्स" के रूप में उपयोग करें:

    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.माता-पिता से विरासत में मिली संपत्ति को पुनः प्राप्त करने के लिए उपयोग करें; यदि बच्चे द्वारा परिभाषित किया गया है, तो child.इसे पुनः प्राप्त करने के लिए उपयोग करें।

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

5

खैर, मैंने इसे दूसरे तरीके से किया। मेरे मामले में मैं एक फ़ंक्शन चाहता था जो अन्य नियंत्रकों में समान फ़ंक्शन और गुण लागू करता है। मुझे यह पसंद आया, मापदंडों को छोड़कर। इस तरह, आपके सभी चाइल्डक्रेल्स को $ स्थान प्राप्त करने की आवश्यकता है।

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

उन लोगों के लिए, आप स्वीकृत उत्तर में विधि का उपयोग करके, उसी तरह से घटक नियंत्रकों का विस्तार कर सकते हैं।

निम्नलिखित दृष्टिकोण का उपयोग करें:

मूल घटक (से विस्तार करने के लिए):

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

चाल को घटक परिभाषा में परिभाषित करने के बजाय, नामित नियंत्रकों का उपयोग करना है।


2

जैसा कि स्वीकार किए गए उत्तर में बताया गया है, आप अपने माता-पिता के नियंत्रक के संशोधनों को $ गुंजाइश और अन्य सेवाओं में कॉल करके "वंशानुक्रम" कर सकते हैं: $controller('ParentCtrl', {$scope: $scope, etc: etc});अपने बच्चे के नियंत्रक में।

हालाँकि , यह विफल हो जाता है यदि आप नियंत्रक को 'सिंटैक्स' के रूप में उपयोग करने के आदी हैं, उदाहरण के लिए

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

यदि fooपैरेंट कंट्रोलर (थ्रू this.foo = ...) में सेट किया गया था , तो चाइल्ड कंट्रोलर के पास इसकी पहुंच नहीं होगी।

जैसा कि टिप्पणियों में उल्लेख किया गया है आप $ कंट्रोलर के परिणाम को सीधे दायरे में रख सकते हैं:

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= , क्योंकि आप कोड में उदाहरण का नाम निर्दिष्ट कर रहे हैं, और अब टेम्पलेट नहीं है।


सिंटैक्स के रूप में "कंट्रोलर" का उपयोग करने से कोई समस्या नहीं है। मेरा उत्तर देखें: stackoverflow.com/a/36549465/2197555
gm2008

2

मैं "नियंत्रक के रूप में" सिंटैक्स का उपयोग कर रहा था vm = thisऔर एक नियंत्रक को प्राप्त करना चाहता था। मेरे माता-पिता नियंत्रक के पास एक फ़ंक्शन था जो एक चर को संशोधित करता है, तो मेरे पास समस्याएं थीं।

IProblemFactory और सलमान अब्बास के उत्तरों का उपयोग करते हुए , मैंने माता-पिता के चर तक पहुंच प्राप्त करने के लिए निम्न कार्य किया:

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


0

आप एक साधारण जावास्क्रिप्ट विरासत तंत्र का उपयोग कर सकते हैं। इसके अलावा .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);

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.