क्या एक कोणीय निर्देश, निर्देश की विशेषताओं में निर्दिष्ट अभिव्यक्तियों के कार्यों के लिए तर्क दे सकता है?


160

मेरे पास एक फार्म निर्देश है जो callbackएक अलग गुंजाइश के साथ एक निर्दिष्ट विशेषता का उपयोग करता है :

scope: { callback: '&' }

यह एक ng-repeatअभिव्यक्ति के भीतर बैठता है जिसे मैं पास करता हूं जिसमें idकॉलबैक फ़ंक्शन के तर्क के रूप में ऑब्जेक्ट शामिल होता है:

<directive ng-repeat = "item in stuff" callback = "callback(item.id)"/>

जब मैंने निर्देशन पूरा कर लिया है, तो यह $scope.callback()अपने नियंत्रक फ़ंक्शन से कॉल करता है। ज्यादातर मामलों के लिए यह ठीक है, और यह सब मैं करना चाहता हूं, लेकिन कभी-कभी मैं directiveखुद के अंदर से एक और तर्क जोड़ना चाहता हूं ।

क्या एक कोणीय अभिव्यक्ति है जो इसे अनुमति देगी: $scope.callback(arg2)जिसके परिणामस्वरूप callbackबुलाया जा रहा है arguments = [item.id, arg2]?

यदि नहीं, तो ऐसा करने का सबसे साफ तरीका क्या है?

मैंने पाया है कि यह काम करता है:

<directive 
  ng-repeat = "item in stuff" 
  callback = "callback" 
  callback-arg="item.id"/>

साथ में

scope { callback: '=', callbackArg: '=' }

और निर्देशन कॉलिंग

$scope.callback.apply(null, [$scope.callbackArg].concat([arg2, arg3]) );

लेकिन मुझे नहीं लगता कि यह विशेष रूप से साफ-सुथरा है और इसमें अतिरिक्त सामान को अलग-अलग दायरे में रखना शामिल है।

क्या कोई बेहतर तरीका है?

प्लंकर खेल का मैदान यहाँ (कंसोल खुला है)।


"कॉलबैक =" नामकरण की विशेषता। यह वास्तव में कॉलबैक मूल्यांकन है, कॉलबैक नहीं है।
दिमित्री जैतसेव

@DmitriZaitsev यह एक कॉलबैक कोणीय अभिव्यक्ति है जो एक जावास्क्रिप्ट फ़ंक्शन का मूल्यांकन करेगा। मुझे लगता है कि यह काफी स्पष्ट है कि यह अपने आप में एक जावास्क्रिप्ट कार्य नहीं है। यह सिर्फ वरीयता है, लेकिन मैं "-प्रचार" के साथ मेरी सभी विशेषताओं को नहीं झेलना पसंद करूंगा। यह ngउदाहरण के लिए एपीआई के अनुरूप ng-click="someFunction()"है एक अभिव्यक्ति है जो एक फ़ंक्शन को निष्पादित करने के लिए मूल्यांकन करता है।
एड हिंचलिफ़

मैंने कभी भी "कॉलबैक" नामक कोणीय अभिव्यक्ति नहीं देखी है। यह हमेशा एक फ़ंक्शन होता है जिसे आप कहा जाता है, नाम का नाम दें। आप अपने उदाहरण में "कॉलबैक" नामक एक फ़ंक्शन का उपयोग करते हैं, चीजों को और अधिक भ्रमित करने के लिए।
दिमित्री ज़ैतसेव

मुझे यकीन नहीं है कि आप भ्रमित हैं या मैं हूं। मेरे उदाहरण में डायरेक्टिव डेफिनेशन ऑब्जेक्ट $scope.callbackकी callback="someFunction"विशेषता और scope: { callback: '=' }संपत्ति द्वारा सेट किया गया है । बाद की तारीख में बुलाया जाने $scope.callback वाला एक कार्य है। वास्तविक विशेषता मान स्पष्ट रूप से एक स्ट्रिंग है - यह हमेशा HTML के साथ होता है।
एड हिंचलिफ़

आप विशेषता और फ़ंक्शन दोनों को नाम देते हैं - "कॉलबैक"। वह भ्रम का नुस्खा है। वास्तव में बचने के लिए आसान।
दिमित्री जैतसेव

जवाबों:


215

यदि आप @ lex82 द्वारा उल्लिखित के रूप में अपने कॉलबैक की घोषणा करते हैं

callback = "callback(item.id, arg2)"

आप ऑब्जेक्ट मैप के साथ निर्देश क्षेत्र में कॉलबैक विधि को कॉल कर सकते हैं और यह बाइंडिंग को सही ढंग से करेगा। पसंद

scope.callback({arg2:"some value"});

$ पैर के लिए आवश्यकता के बिना। मेरी फ़ाइडल (कंसोल लॉग) http://jsfiddle.net/k7czc/2/ देखें

अद्यतन : प्रलेखन में इसका एक छोटा सा उदाहरण है :

& या & attr - माता-पिता के दायरे के संदर्भ में एक अभिव्यक्ति को निष्पादित करने का एक तरीका प्रदान करता है। यदि कोई एटर नाम निर्दिष्ट नहीं है, तो विशेषता नाम को स्थानीय नाम के समान माना जाता है। दिए गए और दायरे की विजेट परिभाषा: {localFn: 'और myAttr'}, फिर अलग-अलग गुंजाइश संपत्ति LocalFn गिनती = गिनती + मूल्य अभिव्यक्ति के लिए एक फ़ंक्शन आवरण की ओर इंगित करेगा। अक्सर यह अलग-अलग दायरे से डेटा को अभिव्यक्ति के माध्यम से और अभिभावक के दायरे में पारित करने के लिए वांछनीय है, यह स्थानीय रैपर नामों और मानों के मानचित्र को अभिव्यक्ति आवरण fn में पास करके किया जा सकता है। उदाहरण के लिए, यदि अभिव्यक्ति वृद्धि (राशि) है, तो हम स्थानीय मान को स्थानीय मान कह कर निर्दिष्ट कर सकते हैं ({राशि: 22})।


4
बहुत अच्छा! क्या यह कहीं भी प्रलेखित है?
ACH

12
मुझे नहीं लगता कि यह एक अच्छा समाधान है क्योंकि निर्देशात्मक परिभाषा में, कभी-कभी आपको नहीं पता होगा कि क्या पास करने के लिए पैरामीटर है।
OMGPOP

यह एक अच्छा समाधान है और इसके लिए आपको धन्यवाद, लेकिन मेरा मानना ​​है कि उत्तर में थोड़ा ज्वार-भाटा की जरूरत है। लेक्स 82 कौन है और उसने क्या उल्लेख किया है?
वेटावर

दिलचस्प दृष्टिकोण। यद्यपि क्या होता है जब आप किसी भी पैरामीटर (या एकाधिक) के साथ किसी भी फ़ंक्शन को पारित करने की अनुमति देना चाहते हैं? आप फ़ंक्शन के कुछ भी नहीं जानते हैं और न ही इसके मापदंडों के बारे में और निर्देश के अंदर किसी घटना पर इसे निष्पादित करने की आवश्यकता है। इसके बारे में कैसे जानें? एक निर्देश पर उदाहरण के लिए आप onchangefunc = 'myCtrlFunc (dynamVariableHere)' कर सकते हैं
ट्रेनोआसिस

58

अन्य उत्तरों के साथ कुछ भी गलत नहीं है, लेकिन मैं निर्देशन विशेषता में कार्य करते समय निम्नलिखित तकनीक का उपयोग करता हूं।

जब आपके html में निर्देश शामिल हो तो कोष्ठक छोड़ दें:

<my-directive callback="someFunction" />

फिर अपने निर्देश के लिंक या नियंत्रक में फ़ंक्शन को "अनफ्रैप" करें। यहाँ एक उदाहरण है:

app.directive("myDirective", function() {

    return {
        restrict: "E",
        scope: {
            callback: "&"                              
        },
        template: "<div ng-click='callback(data)'></div>", // call function this way...
        link: function(scope, element, attrs) {
            // unwrap the function
            scope.callback = scope.callback(); 

            scope.data = "data from somewhere";

            element.bind("click",function() {
                scope.$apply(function() {
                    callback(data);                        // ...or this way
                });
            });
        }
    }
}]);    

"अलिखित" कदम फ़ंक्शन को एक अधिक प्राकृतिक सिंटैक्स का उपयोग करके बुलाया जा सकता है। यह यह भी सुनिश्चित करता है कि निर्देश अन्य फ़ंक्शन के भीतर नेस्टेड होने पर भी ठीक से काम करता है जो फ़ंक्शन को पास कर सकता है। यदि आपने अलिखित नहीं किया है, तो यदि आपके पास इस तरह का परिदृश्य है:

<outer-directive callback="someFunction" >
    <middle-directive callback="callback" >
        <inner-directive callback="callback" />
    </middle-directive>
</outer-directive>

तब आप अपने भीतर के निर्देशन में कुछ इस तरह से खत्म होते हैं:

callback()()()(data); 

जो अन्य घोंसले के शिकार परिदृश्यों में विफल होगा।

मैंने http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-3-isolate-scope-and-function-parameters पर Dan Wahlin के एक उत्कृष्ट लेख से इस तकनीक को अनुकूलित किया

मैंने फ़ंक्शन को अधिक स्वाभाविक बनाने और नेस्टिंग समस्या के समाधान के लिए अलिखित कदम जोड़ा, जो मुझे एक परियोजना में मिला था।


2
एक अच्छा तरीका है, लेकिन मैं thisकॉलबैक विधि के अंदर सूचक का उपयोग करने में सक्षम नहीं हूं , क्योंकि यह निर्देश के दायरे का उपयोग करता है। मैं टाइपस्क्रिप्ट का उपयोग कर रहा हूं और मेरा कॉलबैक इस तरह दिखता है:public validateFirstName(firstName: string, fieldName: string): ng.IPromise<boolean> { var deferred = this.mQService.defer<boolean>(); ... .then(() => deferred.resolve(true)) .catch((msg) => { deferred.reject(false); }); return deferred.promise; }
ndee

1
सूचना: यदि आपके पास निर्देशों का नेस्टेड है और कॉलबैक को ऊपर की ओर फैलाना चाहते हैं, तो आपको प्रत्येक निर्देश में अनचेक करने की आवश्यकता है, न कि केवल एक ट्रिगर कॉलबैक।
एपिसोड 15

43

निर्देश में ( myDirective):

...
directive.scope = {  
    boundFunction: '&',
    model: '=',
};
...
return directive;

निर्देश टेम्पलेट में:

<div 
data-ng-repeat="item in model"  
data-ng-click='boundFunction({param: item})'>
{{item.myValue}}
</div>

स्रोत में:

<my-directive 
model='myData' 
bound-function='myFunction(param)'>
</my-directive>

... जहां myFunctionनियंत्रक में परिभाषित किया गया है।

ध्यान दें कि paramनिर्देश टेम्पलेट paramमें स्रोत में बड़े करीने से बांधता है , और करने के लिए सेट है item


linkएक निर्देश की संपत्ति के भीतर से कॉल करने के लिए ("इसके अंदर"), एक बहुत ही समान दृष्टिकोण का उपयोग करें:

...
directive.link = function(isolatedScope) {
    isolatedScope.boundFunction({param: "foo"});
};
...
return directive;

स्रोत में होने के दौरान: बाउंड-फ़ंक्शन = 'myFunction (obj1.param, obj2.param)'> फिर कैसे आगे बढ़ना है?
अंकित पांडे

15

हां, एक बेहतर तरीका है: आप अपने निर्देशन में केवल दिखाई देने वाले मूल्यों के लिए कुछ पहचानकर्ताओं को अभिव्यक्ति में बाँधते समय पैरेंट स्कोप के संदर्भ में एक अभिव्यक्ति का मूल्यांकन करने के लिए अपने निर्देश में $ पार्स सेवा का उपयोग कर सकते हैं :

$parse(attributes.callback)(scope.$parent, { arg2: yourSecondArgument });

इस लाइन को निर्देश के लिंक फ़ंक्शन में जोड़ें जहां आप निर्देश की विशेषताओं तक पहुंच सकते हैं।

आपकी कॉलबैक विशेषता तब सेट की जा सकती है callback = "callback(item.id, arg2)"क्योंकि arg2 निर्देश के अंदर $ parse सेवा द्वारा आपकेSecondArgument के लिए बाध्य है। निर्देश जैसे ng-clickकि आप $eventइस तंत्र का उपयोग करके निर्देश को दिए गए अभिव्यक्ति के अंदर पहचानकर्ता के माध्यम से क्लिक इवेंट तक पहुंचने देते हैं ।

ध्यान दें कि आपको callbackइस समाधान के साथ अपने पृथक दायरे का सदस्य बनाने की आवश्यकता नहीं है ।


3
scope.$parentनिर्देशन "लीक" का उपयोग करता है - यह "जानता है" बाहरी दुनिया का बहुत अधिक है, जिसे एक अच्छी तरह से डिज़ाइन किए गए एन्कैप्सुलेटेड घटक को नहीं करना चाहिए।
दिमित्री ज़ैतसेव

3
ठीक है, यह जानता है कि इसका एक मूल क्षेत्र है, लेकिन यह क्षेत्र में किसी विशेष क्षेत्र तक नहीं पहुंचता है इसलिए मुझे लगता है कि यह सहनीय है।
lex82

0

मेरे लिए निम्नलिखित काम किया:

निर्देशन में इसे इस तरह घोषित करें:

.directive('myDirective', function() {
    return {
        restrict: 'E',
        replace: true,
        scope: {
            myFunction: '=',
        },
        templateUrl: 'myDirective.html'
    };
})  

निर्देशात्मक टेम्पलेट में इसे निम्न तरीके से उपयोग करें:

<select ng-change="myFunction(selectedAmount)">

और फिर जब आप निर्देश का उपयोग करते हैं, तो फ़ंक्शन को इस तरह से पास करें:

<data-my-directive
    data-my-function="setSelectedAmount">
</data-my-directive>

आप फ़ंक्शन को इसकी घोषणा से पारित करते हैं और इसे निर्देश से बुलाया जाता है और मापदंडों को आबादी दी जाती है।

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