अन्य नियंत्रक से निर्देश नियंत्रक में कॉल विधि


118

मेरे पास एक निर्देश है जिसका अपना नियंत्रक है। नीचे दिया गया कोड देखें:

var popdown = angular.module('xModules',[]);

popdown.directive('popdown', function () {
    var PopdownController = function ($scope) {
        this.scope = $scope;
    }

    PopdownController.prototype = {
        show:function (message, type) {
            this.scope.message = message;
            this.scope.type = type;
        },

        hide:function () {
            this.scope.message = '';
            this.scope.type = '';
        }
    }

    var linkFn = function (scope, lElement, attrs, controller) {

    };

    return {
        controller: PopdownController,
        link: linkFn,
        replace: true,
        templateUrl: './partials/modules/popdown.html'
    }

});

इसका मतलब त्रुटियों / सूचनाओं / चेतावनियों के लिए एक अधिसूचना प्रणाली होना है। showइस नियंत्रक पर फ़ंक्शन को कॉल करने के लिए मैं जो करना चाहता हूं वह किसी अन्य नियंत्रक (एक निर्देश नहीं) से है । और जब मैं ऐसा करता हूं, तो मैं यह भी चाहूंगा कि मेरा लिंक फ़ंक्शन यह पता लगाए कि कुछ गुण बदल गए और कुछ एनिमेशन किए।

यहाँ कुछ कोड का उदाहरण दिया गया है जो मैं पूछ रहा हूँ:

var app = angular.module('app', ['RestService']);

app.controller('IndexController', function($scope, RestService) {
    var result = RestService.query();

    if(result.error) {
        popdown.notify(error.message, 'error');
    }
});

इसलिए निर्देश नियंत्रक showपर कॉल करते समय popdown, लिंक फ़ंक्शन को भी ट्रिगर किया जाना चाहिए और एक एनीमेशन करना चाहिए। मैं इसे कैसे हासिल कर सकता हूं?


आप popdownपृष्ठ पर निर्देश को कॉल कहाँ रख रहे हैं - क्या यह सिर्फ एक ही स्थान पर है जहाँ अन्य नियंत्रकों को माना जाता है कि सभी को इसकी पहुँच प्राप्त है, या विभिन्न स्थानों में कई पॉपडाउन हैं?
साचमोरुन

मेरे index.html में यह है: <div ng-view> </ div> <div popdown> </ div> मूल रूप से केवल 1 पॉपडाउन उदाहरण है क्योंकि इसका वैश्विक रूप से उपलब्ध होना है।
user253530

1
मुझे लगता है कि आप लिखने के popdown.show(...)बजाय इसका मतलब popdown.notify(...)है कि सही है? अन्यथा नोटिफ़िकेशन फ़ंक्शन एक प्रकार का भ्रामक है
lanoxx

वह कहाँ से आता है popdown.notify? .notifiyविधि, मेरा मतलब है
ग्रीन

जवाबों:


167

यह एक दिलचस्प सवाल है, और मैं यह सोचने लगा कि मैं इस तरह से कुछ कैसे लागू करूंगा।

मैं इस (बेला) के साथ आया था ;

मूल रूप से, एक नियंत्रक से एक निर्देश को कॉल करने की कोशिश करने के बजाय, मैंने सभी पॉपडाउन लॉजिक के लिए एक मॉड्यूल बनाया:

var PopdownModule = angular.module('Popdown', []);

मैंने मॉड्यूल में दो चीजें डालीं , एक factoryएपीआई के लिए जिसे कहीं भी इंजेक्ट किया जा सकता है, और directiveवास्तविक डाउनडाउन तत्व के व्यवहार को परिभाषित करने के लिए:

कारखाने सिर्फ कार्यों के एक जोड़े को परिभाषित करता है successऔर errorऔर चर के एक जोड़े का ट्रैक रखता है:

PopdownModule.factory('PopdownAPI', function() {
    return {
        status: null,
        message: null,
        success: function(msg) {
            this.status = 'success';
            this.message = msg;
        },
        error: function(msg) {
            this.status = 'error';
            this.message = msg;
        },
        clear: function() {
            this.status = null;
            this.message = null;
        }
    }
});

निर्देश एपीआई को इसके नियंत्रक में इंजेक्ट किया जाता है, और परिवर्तनों के लिए एपीआई देखता है (मैं सुविधा के लिए बूटस्ट्रैप सीएसएस का उपयोग कर रहा हूं):

PopdownModule.directive('popdown', function() {
    return {
        restrict: 'E',
        scope: {},
        replace: true,
        controller: function($scope, PopdownAPI) {
            $scope.show = false;
            $scope.api = PopdownAPI;

            $scope.$watch('api.status', toggledisplay)
            $scope.$watch('api.message', toggledisplay)

            $scope.hide = function() {
                $scope.show = false;
                $scope.api.clear();
            };

            function toggledisplay() {
                $scope.show = !!($scope.api.status && $scope.api.message);               
            }
        },
        template: '<div class="alert alert-{{api.status}}" ng-show="show">' +
                  '  <button type="button" class="close" ng-click="hide()">&times;</button>' +
                  '  {{api.message}}' +
                  '</div>'
    }
})

फिर मैं एक appमॉड्यूल को परिभाषित करता हूं जो इस पर निर्भर करता है Popdown:

var app = angular.module('app', ['Popdown']);

app.controller('main', function($scope, PopdownAPI) {
    $scope.success = function(msg) { PopdownAPI.success(msg); }
    $scope.error   = function(msg) { PopdownAPI.error(msg); }
});

और HTML जैसा दिखता है:

<html ng-app="app">
    <body ng-controller="main">
        <popdown></popdown>
        <a class="btn" ng-click="success('I am a success!')">Succeed</a>
        <a class="btn" ng-click="error('Alas, I am a failure!')">Fail</a>
    </body>
</html>

मुझे यकीन नहीं है कि यह पूरी तरह से आदर्श है, लेकिन यह वैश्विक-ईश पॉपडाउन निर्देश के साथ संचार स्थापित करने के लिए एक उचित तरीके की तरह लग रहा था।

फिर से, संदर्भ के लिए, बेला


10
+1 किसी को कभी भी किसी निर्देश को निर्देश के बाहर से नहीं बुलाना चाहिए - यह बुरा व्यवहार है। वैश्विक स्थिति का प्रबंधन करने के लिए एक सेवा का उपयोग करना जो एक निर्देश पढ़ता है सुपर सामान्य है और यह सही दृष्टिकोण है। अधिक एप्लिकेशन में अधिसूचना कतार और मोडल संवाद शामिल हैं।
जोश डेविड मिलर

7
वास्तव में असाधारण जवाब! JQuery और बैकबोन से आने वाले लोगों के लिए इस तरह का एक उपयोगी उदाहरण
ब्रैंडन

11
इस तरह एक ही दृश्य में कई निर्देशों को पलटने के लिए इस मॉड्यूल का उपयोग करना संभव है? मैं इस निर्देश के किसी विशेष उदाहरण की सफलता या त्रुटि फ़ंक्शन को कैसे कह सकता हूं?
इरा

3
@ira शायद आप स्थिति और संदेश ऑब्जेक्ट्स का एक नक्शा (या सूची) रखने के लिए कारखाने को बदल सकते हैं और फिर निर्देश पर एक नाम विशेषता का उपयोग कर सकते हैं कि आपको उस सूची में किस आइटम की आवश्यकता है। इसलिए success(msg)html में कॉल करने के बजाय आप sucess(name, msg)सही नाम के साथ निर्देश का चयन करने के लिए कहेंगे ।
lanoxx

5
@JoshDavidMiller एक निर्देश पर एक विधि को कॉल करने के लिए आप इसे बुरा अभ्यास क्यों मानते हैं? यदि कोई निर्देश कुछ DOM लॉजिक को इरादा के अनुसार एनकैप्सुलेट करता है, तो निश्चित रूप से एक एपीआई को उजागर करना काफी स्वाभाविक है ताकि नियंत्रक जो इसका उपयोग करते हैं वे आवश्यकतानुसार इसके तरीकों को लागू कर सकें?
पॉल टेलर

27

आप पॉपडाउन को ट्रिगर करने के लिए घटनाओं का भी उपयोग कर सकते हैं।

यहाँ satchmorun के समाधान पर आधारित एक फिडेल है। यह पॉपडाउनएपीआई और शीर्ष-स्तरीय नियंत्रक के बजाय $broadcast'सफलता' और 'त्रुटि' की घटनाओं की गुंजाइश श्रृंखला को नीचे कर देता है:

$scope.success = function(msg) { $scope.$broadcast('success', msg); };
$scope.error   = function(msg) { $scope.$broadcast('error', msg); };

फिर पॉपडाउन मॉड्यूल इन घटनाओं के लिए हैंडलर कार्यों को पंजीकृत करता है, जैसे:

$scope.$on('success', function(event, msg) {
    $scope.status = 'success';
    $scope.message = msg;
    $scope.toggleDisplay();
});

यह काम करता है, कम से कम, और मुझे एक अच्छी तरह से विघटित समाधान लगता है। अगर किसी कारण से यह खराब अभ्यास माना जाता है तो मैं दूसरों को झंकारने दूँगा।


1
एक दोष जो मैं सोच सकता हूं वह यह है कि चयनित उत्तर में आपको केवल पॉपडाउनएपीआई (डीआई के साथ आसानी से उपलब्ध) की आवश्यकता है। इसमें आपको संदेश को प्रसारित करने के लिए नियंत्रक के दायरे तक पहुंच की आवश्यकता होती है। वैसे भी, यह बहुत संक्षिप्त लगता है।
जूलियन

मुझे यह सरल उपयोग के मामलों के लिए सेवा-दृष्टिकोण से बेहतर लगता है क्योंकि यह जटिलता को कम रखता है और अभी भी शिथिल है
पैट्रिक फेवरे

11

आप माता-पिता के दायरे के निर्देश के नियंत्रक को भी उजागर कर सकते हैं, जैसे विशेषता के ngFormसाथ nameहै: http://docs.angularjs.org/api/ng.directive:ngForm

यहां आप एक बहुत ही बुनियादी उदाहरण पा सकते हैं कि इसे कैसे प्राप्त किया जा सकता है http://plnkr.co/edit/Ps8OXrfpnePFvvdFgYJf?p=preview

इस उदाहरण में मेरे पास विधि के myDirectiveसाथ समर्पित नियंत्रक है $clear(निर्देश के लिए बहुत ही सरल सार्वजनिक एपीआई की तरह)। मैं इस नियंत्रक को मूल दायरे में प्रकाशित कर सकता हूं और निर्देश के बाहर इस पद्धति का उपयोग कर सकता हूं।


यह नियंत्रकों के बीच संबंध की आवश्यकता है, है ना? चूंकि ओपी एक संदेश केंद्र चाहता था, इसलिए यह उसके लिए आदर्श नहीं हो सकता है। लेकिन साथ ही साथ अपने दृष्टिकोण को सीखना बहुत अच्छा था। यह कई स्थितियों में उपयोगी है और, जैसा आपने कहा, कोणीय स्वयं इसका उपयोग करता है।
fasfsfgs

मैं साचमोरुन द्वारा प्रदान किए गए एक उदाहरण का पालन करने की कोशिश कर रहा हूं। मैं रनटाइम पर कुछ html उत्पन्न कर रहा हूं, लेकिन मैं निर्देश के टेम्पलेट का उपयोग नहीं कर रहा हूं। मैं ऐडेड को जोड़ने के लिए फंक्शन निर्दिष्ट करने के लिए डायरेक्टिव कंट्रोलर का उपयोग कर रहा हूं लेकिन फंक्शन को कॉल नहीं किया जा रहा है। असल में, मेरे पास यह निर्देश है: directives.directive ('abcXyz', function ($ संकलन {वापसी {प्रतिबंधित: 'AE'), आवश्यकता: 'ngModel', नियंत्रक: समारोह ($ गुंजाइश) {$ गुंजाइश .function1 = function () {..};}, मेरा html है: "<a href="" ng-click="function1('itemtype')">
Mark

यह एकमात्र सुरुचिपूर्ण समाधान है जो निर्देश एफी को उजागर कर सकता है यदि निर्देश एकल नहीं है! मुझे अभी भी उपयोग करना पसंद नहीं है $scope.$parent[alias]क्योंकि यह मेरे लिए गंध है जैसे कि आंतरिक कोणीय एपीआई का उपयोग करना। लेकिन अभी भी नहीं-एकल निर्देश के लिए और अधिक सुरुचिपूर्ण समाधान नहीं मिल सकता है। अन्य संस्करण जैसे प्रसारण कार्यक्रम या मूल एपीआई के लिए मूल नियंत्रक में खाली वस्तु को परिभाषित करना और भी अधिक बदबू आ रही है।
रुस्लान Stelmachenko

3

मुझे बहुत बेहतर समाधान मिला।

यहाँ मेरा निर्देश है, मैंने निर्देश में ऑब्जेक्ट संदर्भ पर इंजेक्शन लगाया है और निर्देश कोड में इनवोक फ़ंक्शन जोड़कर इसका विस्तार किया है।

app.directive('myDirective', function () {
    return {
        restrict: 'E',
        scope: {
        /*The object that passed from the cntroller*/
        objectToInject: '=',
        },
        templateUrl: 'templates/myTemplate.html',

        link: function ($scope, element, attrs) {
            /*This method will be called whet the 'objectToInject' value is changes*/
            $scope.$watch('objectToInject', function (value) {
                /*Checking if the given value is not undefined*/
                if(value){
                $scope.Obj = value;
                    /*Injecting the Method*/
                    $scope.Obj.invoke = function(){
                        //Do something
                    }
                }    
            });
        }
    };
});

एक पैरामीटर के साथ HTML में निर्देश की घोषणा:

<my-directive object-to-inject="injectedObject"></ my-directive>

मेरा नियंत्रक:

app.controller("myController", ['$scope', function ($scope) {
   // object must be empty initialize,so it can be appended
    $scope.injectedObject = {};

    // now i can directly calling invoke function from here 
     $scope.injectedObject.invoke();
}];

यह मूल रूप से चिंताओं के सिद्धांतों के अलगाव के खिलाफ जाता है। आप किसी कंट्रोलर में इंस्टेंट किए गए ऑब्जेक्ट को निर्देश देने के लिए प्रदान करते हैं, और आप उस ऑब्जेक्ट को प्रबंधित करने की जिम्मेदारी (यानी इनवोक फ़ंक्शन का निर्माण) को निर्देश देते हैं। मेरी राय में, बेहतर समाधान नहीं है।
फ्लोरिन विस्टिग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.