AngularJS। नियंत्रक घटक के बाहर से नियंत्रक फ़ंक्शन को कैसे कॉल करें


190

मैं वेब पेज (नियंत्रक घटक के बाहर) के किसी भी स्थान से नियंत्रक के तहत फ़ंक्शन को कैसे कॉल कर सकता हूं?

यह पूरी तरह से काम करता है जब मैं "गेट" बटन दबाता हूं। लेकिन मुझे इसे डिव कंट्रोलर के बाहर से बुलाना होगा। तर्क है: डिफ़ॉल्ट रूप से मेरा div छिपा हुआ है। कहीं नेविगेशन मेनू में मैं एक बटन दबाता हूं और यह दिखाना चाहिए () मेरी div और निष्पादित "प्राप्त करें" फ़ंक्शन। मैं इसे कैसे प्राप्त कर सकता हूं?

मेरा वेब पेज है:

<div ng-controller="MyController">
  <input type="text" ng-model="data.firstname" required>
  <input type='text' ng-model="data.lastname" required>

  <form ng-submit="update()"><input type="submit" value="update"></form>
  <form ng-submit="get()"><input type="submit" value="get"></form>
</div>

मेरे जेएस:

   function MyController($scope) {
      // default data and structure
      $scope.data = {
        "firstname" : "Nicolas",
        "lastname" : "Cage"
      };

      $scope.get = function() {
        $.ajax({
           url: "/php/get_data.php?",
           type: "POST",
           timeout: 10000, // 10 seconds for getting result, otherwise error.
           error:function() { alert("Temporary error. Please try again...");},
           complete: function(){ $.unblockUI();},
           beforeSend: function(){ $.blockUI()},
           success: function(data){
            json_answer = eval('(' + data + ')');
            if (json_answer){
                $scope.$apply(function () {
                  $scope.data = json_answer;
            });
            }
        }
    });
  };

  $scope.update = function() {
    $.ajax({
        url: "/php/update_data.php?",
        type: "POST",
        data: $scope.data,
        timeout: 10000, // 10 seconds for getting result, otherwise error.
        error:function() { alert("Temporary error. Please try again...");},
        complete: function(){ $.unblockUI();},
        beforeSend: function(){ $.blockUI()},
        success: function(data){ }
      });
    };
   }

2
जब आप कहते हैं "... कहीं नेविगेशन मेनू में आप एक बटन दबाते हैं ...", तो क्या आपके कहने का मतलब यह है कि यह नेविगेशन किसी अन्य नियंत्रक का हिस्सा है और आप दूसरे नियंत्रक get()से MyController के कॉल करना चाहते हैं ?
callmekatootie

1
अभी के लिए नेविगेशन मेनू नियंत्रक नहीं है। बस html। यकीन नहीं है कि अगर यह html / जावास्क्रिप्ट से नियंत्रक फ़ंक्शन को कॉल करना संभव है, तो यही कारण है कि मैंने यह प्रश्न पोस्ट किया है। लेकिन हाँ, अलग नियंत्रक के रूप में नेविगेशन मेनू बनाने के लिए तार्किक। मैं नेविगेशनमेन्यू.कंट्रोलर से MyController.get () फ़ंक्शन को कैसे कॉल कर सकता हूं?
पावेल ज़ैड्रोव

जवाबों:


331

यहाँ इसके बाहर से नियंत्रक के कार्य को कॉल करने का एक तरीका है:

angular.element(document.getElementById('yourControllerElementID')).scope().get();

get()आपके नियंत्रक से एक फ़ंक्शन कहां है।

आप स्विच कर सकते हैं

document.getElementById('yourControllerElementID')` 

सेवा

$('#yourControllerElementID')

यदि आप jQuery का उपयोग कर रहे हैं।

साथ ही, यदि आपके फ़ंक्शन का अर्थ है कि आपके व्यू पर कुछ भी बदल रहा है, तो आपको कॉल करना चाहिए

angular.element(document.getElementById('yourControllerElementID')).scope().$apply();

परिवर्तनों को लागू करने के लिए।

एक और बात, आपको ध्यान देना चाहिए कि पेज लोड होने के बाद स्कोप को इनिशियलाइज़ किया जाता है, इसलिए पेज लोड होने के बाद स्कोप के बाहर से कॉलिंग के तरीके हमेशा होने चाहिए। वरना आपको गुंजाइश बिल्कुल नहीं मिलेगी।

अपडेट करें:

कोणीय के नवीनतम संस्करणों के साथ, आपको उपयोग करना चाहिए

angular.element(document.getElementById('yourControllerElementID')).injector().‌​get('$rootScope')

और हां, यह वास्तव में, एक बुरा अभ्यास है , लेकिन कभी-कभी आपको बस जल्दी और गंदी चीजों की आवश्यकता होती है।


30
ऐसा लगता है जैसे
कोड्यूलर

8
इसलिए यदि आप कोणीय कोड के साथ DOM कोड को मिक्स नहीं करना चाहते हैं, यदि आप चाहते हैं कि कुछ JQuery एनिमेशन आपके Angular कंट्रोलर में परिवर्तनशील परिवर्तन की प्रतिक्रिया में आग लगा दें- तो आप वास्तव में ऐसा कैसे करते हैं? यह नियंत्रक से करने के लिए तुच्छ होगा, लेकिन मुझे नहीं पता कि इसे कैसे साफ किया जाए
Jan

3
$applyजब तक मैंने एक समारोह में कोड नहीं लपेटा, तब तक मुझे मेरे लिए काम करने का हिस्सा नहीं मिला , उदाहरण के लिए..scope.$apply(function() { scope.get() });
सर्टक्रिटिट

2
मैं वास्तव में angular.element(document.getElementById('yourControllerElementID')).scope().controller; पूर्व के साथ नियंत्रक का उपयोग कर सकता है । अगर उपयोग करें: angular.element(document.getElementById('controller')).scope().get() फेंकता है और अपरिभाषित त्रुटि होती है, लेकिन अगर मैं इसका उपयोग angular.element(document.getElementById('controller')).scope().controller.get()करता हूं ।
vrunoa

2
क्या यह संभव है, कि यह समाधान Angular 1.4.9 में अब काम नहीं करता है? मैं नहीं पहुंच सकते scope()में angular.element(...)है क्योंकि यह अपरिभाषित वापसी और कोणीय तत्व / वस्तु का एक vardump का कहना है कि समारोह, scopeके भीतर स्थित है __proto__-object।
स्मामति

37

मुझे इंटरनेट पर एक उदाहरण मिला है।

कुछ लोगों ने इस कोड को लिखा और पूरी तरह से काम किया

एचटीएमएल

<div ng-cloak ng-app="ManagerApp">
    <div id="MainWrap" class="container" ng-controller="ManagerCtrl">
       <span class="label label-info label-ext">Exposing Controller Function outside the module via onClick function call</span>
       <button onClick='ajaxResultPost("Update:Name:With:JOHN","accept",true);'>click me</button>
       <br/> <span class="label label-warning label-ext" ng-bind="customParams.data"></span>
       <br/> <span class="label label-warning label-ext" ng-bind="customParams.type"></span>
       <br/> <span class="label label-warning label-ext" ng-bind="customParams.res"></span>
       <br/>
       <input type="text" ng-model="sampletext" size="60">
       <br/>
    </div>
</div>

JAVASCRIPT

var angularApp = angular.module('ManagerApp', []);
angularApp.controller('ManagerCtrl', ['$scope', function ($scope) {

$scope.customParams = {};

$scope.updateCustomRequest = function (data, type, res) {
    $scope.customParams.data = data;
    $scope.customParams.type = type;
    $scope.customParams.res = res;
    $scope.sampletext = "input text: " + data;
};



}]);

function ajaxResultPost(data, type, res) {
    var scope = angular.element(document.getElementById("MainWrap")).scope();
    scope.$apply(function () {
    scope.updateCustomRequest(data, type, res);
    });
}

डेमो

* मैंने कुछ संशोधन किए, मूल देखें: फ़ॉन्ट JSfiddle


2
धन्यवाद रोजर, बहुत उपयोगी!
एडुआर्डो

एक विरासत jQuery सत्यापन पुस्तकालय के साथ काम करना चाहिए जिसका उपयोग किया जाना चाहिए। तो, यह 1 या तो है: लाइब्रेरी को फिर से लिखना, 2: लाइब्रेरी को लपेटने का निर्देश बनाना, 3: 2 लाइनों के कोड को कोणीय सबमिट करने के लिए जब वैध कहते हैं ...
माइकल के

अगर मैं आवेदन का उपयोग नहीं करता हूं, तो फ़ंक्शन जो दृश्य डेटा को अपडेट करेगा, प्रतिबिंबित नहीं होगा?
मनोजित सरकार

13

समाधान angular.element(document.getElementById('ID')).scope().get()ने मेरे लिए कोणीय 1.5.2 में काम करना बंद कर दिया। सोमबॉडी ने एक टिप्पणी में उल्लेख किया है कि यह 1.4.9 में भी काम नहीं करता है। मैंने इसे वैश्विक वैरिएबल में स्कोप जमा करके तय किया:

var scopeHolder;
angular.module('fooApp').controller('appCtrl', function ($scope) {
    $scope = function bar(){
        console.log("foo");        
    };
    scopeHolder = $scope;
})

कस्टम कोड से कॉल करें:

scopeHolder.bar()

यदि आप केवल इस पद्धति के दायरे को सीमित करना चाहते हैं। पूरे दायरे के जोखिम को कम करने के लिए। निम्नलिखित तकनीक का उपयोग करें।

var scopeHolder;
angular.module('fooApp').controller('appCtrl', function ($scope) {
    $scope.bar = function(){
        console.log("foo");        
    };
    scopeHolder = $scope.bar;
})

कस्टम कोड से कॉल करें:

scopeHolder()

यह मेरे लिए बहुत अच्छा काम करता था (एक घटक के अंदर से भी)। क्या ऐसा करने के लिए एक नकारात्मक पहलू यह है कि "कोणीय सामान को बाहरी कोणीय से कॉल करने के लिए खराब अभ्यास" के अलावा मैं अपने परिदृश्य से बचने में सक्षम नहीं हूं? stackoverflow.com/questions/42123120/…
RichC

आपकी मदद के लिए धन्यवाद सर, मैं थोड़ी देर से इसके समाधान की खोज कर रहा था
इब्राहिम आमेर

11

दिमित्री का जवाब ठीक काम करता है। मैंने बस उसी तकनीक का उपयोग करके एक सरल उदाहरण बनाया है।

jsfiddle: http://jsfiddle.net/o895a8n8/5/

<button onclick="call()">Call Controller's method from outside</button>
<div  id="container" ng-app="" ng-controller="testController">
</div>

function call() {
    var scope = angular.element(document.getElementById('container')).scope();
      scope.$apply(function(){
        scope.msg = scope.msg + ' I am the newly addded message from the outside of the controller.';
    })
    alert(scope.returnHello());
}

function testController($scope) {
    $scope.msg = "Hello from a controller method.";
    $scope.returnHello = function() {
        return $scope.msg ; 
    }
}

7

मैं कारखाने को नियंत्रकों पर निर्भरता के रूप में कोड की अपनी लाइन के साथ इंजेक्ट करने की बजाय शामिल करूंगा: http://jsfiddle.net/XqDxG/550/

myModule.factory('mySharedService', function($rootScope) {
    return sharedService = {thing:"value"};
});

function ControllerZero($scope, mySharedService) {
    $scope.thing = mySharedService.thing;

कंट्रोलरजेरो। $ इंजेक्षन = ['$ स्कोप', 'मायशेड सर्विस'];


हम्म। @ एटन ने नीचे (मई '13 में) एक बेला टिप्पणी की, जो दोनों को करती है।
जेसी चिशोल्म

5

यह विचार करने योग्य हो सकता है कि क्या आपके मेनू में बिना किसी संबंधित गुंजाइश के जाने का सही तरीका है। यह वास्तव में कोणीय तरीका नहीं है।

लेकिन, अगर यह वह तरीका है जिसे आपको जाने की आवश्यकता है, तो आप इसे $ rootScope में फ़ंक्शन जोड़कर कर सकते हैं और फिर घटनाओं को भेजने के लिए $ प्रसारण का उपयोग करके उन कार्यों के भीतर कर सकते हैं। आपका नियंत्रक तब उन घटनाओं को सुनने के लिए $ का उपयोग करता है।

एक और बात पर विचार करें कि यदि आप बिना किसी दायरे के अपने मेनू को समाप्त करते हैं, तो यदि आपके पास कई मार्ग हैं, तो आपके सभी नियंत्रकों को अपना स्वयं का कार्य करना होगा और कार्य करने होंगे। (यह मान लिया गया है कि आपके पास कई नियंत्रक हैं)


आप कैसे कॉल करने के लिए कोई भी सरल उदाहरण दे सकते हैं। मेरा तर्क इतना है कि प्रत्येक नियंत्रक के पास अपने .get () .update () फ़ंक्शन होंगे। मेरे पास MainMenuController होगी जिसमें से मुझे आवश्यक मेनू के अनुसार (मेनू आइटम के अनुसार) .get () निष्पादित करना होगा।
पावेल ज़ैड्रोव

पीएस, मेरा कोड नहीं है, लेकिन यह दिखाता है कि कार्यक्षमता को साझा करने वाले कई कंट्रोलर कैसे हैं
एंटोन

4

मैं $ http के साथ काम करने के लिए उपयोग करता हूं, जब मैं एक संसाधन से कुछ जानकारी प्राप्त करना चाहता हूं जो मैं निम्नलिखित करता हूं:

angular.module('services.value', [])

.service('Value', function($http, $q) {

var URL = "http://localhost:8080/myWeb/rest/";

var valid = false;

return {
    isValid: valid,
    getIsValid: function(callback){
        return $http.get(URL + email+'/'+password, {cache: false})
                    .success(function(data){
            if(data === 'true'){ valid = true; }
        }).then(callback);
    }}
    });

और नियंत्रक में कोड:

angular.module('controllers.value', ['services.value'])

.controller('ValueController', function($scope, Value) {
    $scope.obtainValue = function(){
        Value.getIsValid(function(){$scope.printValue();});
    }

    $scope.printValue = function(){
        console.log("Do it, and value is " Value.isValid);
    }
}

मैं नियंत्रक को कॉल करने के लिए फ़ंक्शन को सेवा में भेजता हूं


3

मेरे पास कई मार्ग और कई नियंत्रक हैं, इसलिए मुझे काम करने के लिए स्वीकृत जवाब नहीं मिला। मैंने पाया कि फ़ंक्शन को विंडो में जोड़ना काम करता है:

fooModule.controller("fooViewModel", function ($scope, fooService, $http, $q, $routeParams, $window, $location, viewModelHelper, $interval) {
    $scope.initFoo = function () {
        // do angular stuff
    }
    var initialize = function () {
        $scope.initFoo();
    }

    initialize();

    window.fooreinit = initialize;

}

फिर नियंत्रक के बाहर, यह किया जा सकता है:

function ElsewhereOnThePage() {
    if (typeof(fooreinit) == 'function') { fooreinit(); }
}

0

कंट्रोलर के बाहर से कोणीय स्कोप फ़ंक्शन को कॉल करें।

// Simply Use "Body" tag, Don't try/confuse using id/class.

var scope = angular.element('body').scope();             
scope.$apply(function () {scope.YourAngularJSFunction()});      

-1

मैं एक आयोनिक फ्रेमवर्क उपयोगकर्ता हूं और मैंने पाया कि वर्तमान नियंत्रक की $ गुंजाइश लगातार प्रदान करेगा:

angular.element(document.querySelector('ion-view[nav-view="active"]')).scope()

मुझे संदेह है कि यह फ्रेमवर्क की परवाह किए बिना अधिकांश परिदृश्यों को फिट करने के लिए संशोधित किया जा सकता है (या नहीं) उस क्वेरी को खोजकर जो विशिष्ट डोम तत्व (ओं) को लक्षित करेगा जो किसी दिए गए नियंत्रक उदाहरण के दौरान ही उपलब्ध हैं।

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