कोणीयज निर्देश कॉल फ़ंक्शन विशेषता में निर्दिष्ट है और इसके लिए एक तर्क पास करते हैं


102

मैं एक निर्देश बनाना चाहता हूं जो एक विशेषता से जुड़ा हो। विशेषता उस फ़ंक्शन को निर्दिष्ट करती है जिसे गुंजाइश पर बुलाया जाना चाहिए। लेकिन मैं फ़ंक्शन के लिए एक तर्क भी पारित करना चाहता हूं जो लिंक फ़ंक्शन के अंदर निर्धारित होता है।

<div my-method='theMethodToBeCalled'></div>

लिंक फ़ंक्शन में, मैं एक jQuery इवेंट से जुड़ता हूं, जो एक तर्क देता है जिसे मुझे फ़ंक्शन को पास करने की आवश्यकता है:

app.directive("myMethod",function($parse) {
  restrict:'A',
  link:function(scope,element,attrs) {
     var expressionHandler = $parse(attrs.myMethod);
     $(element).on('theEvent',function( e, rowid ) {
        id = // some function called to determine id based on rowid
        scope.$apply(function() {expressionHandler(id);});
     }
  }
}

app.controller("myController",function($scope) {
   $scope.theMethodToBeCalled = function(id) { alert(id); };
}

आईडी पास किए बिना मैं इसे काम कर सकता हूं, लेकिन जैसे ही मैं एक तर्क पारित करने की कोशिश करता हूं, फ़ंक्शन को अब नहीं बुलाया जाता है


दो-तरफ़ा बंधन के बिना अलग-अलग गुंजाइश के माध्यम से ऑब्जेक्ट संपत्ति तक कैसे पहुंचें? मुझे लगता है कि यह मददगार है। पृथक स्कोप का उपयोग करें, और $ स्कोप के
JJbang

जवाबों:


98

मार्को का समाधान अच्छी तरह से काम करता है

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

टेम्पलेट में

<div my-method="theMethodToBeCalled(myParam)"></div>

निर्देशन लिंक फ़ंक्शन में

$(element).click(function( e, rowid ) {
  scope.method({myParam: id});
});

मार्को के समाधान की तुलना में इसका एक नुकसान है - पहले लोड परMethodToBeCalled फ़ंक्शन को myParam === के साथ अपरिभाषित किया जाएगा।

एक वर्किंग एग्जाम @treeface Plunker पर पाया जा सकता है


दरअसल, कस्टम विशेषता में पैरामीटर के साथ फ़ंक्शन नाम प्रदान करने का यह पैटर्न निर्देशों में "कॉलबैक फ़ंक्शंस" को परिभाषित करने का सबसे आसान और सबसे मजबूत तरीका लगता है ... thx !!
rekna

3
"सेटप्रोडक्ट" 2 अलग-अलग चीजों को कॉल करना बहुत भ्रामक है - विशेषता और गुंजाइश फ़ंक्शन, यह समझना मुश्किल है कि कौन सा कहाँ है।
दिमित्री ज़ैतसेव

व्हाट्सएप भ्रमित कर रहा है कि क्यों सही उत्तर अलग-थलग गुंजाइश का उपयोग कर रहा है लेकिन सवाल नहीं करता है। या क्या मैं कुछ न कुछ भूल रहा हूं?
j_walker_dev

मेरे परीक्षणों से कोणीय 1.2.28 में इस कोड का उपयोग करके, यह अच्छी तरह से काम करता है। मेरे परीक्षण पहले लोड पर अपरिभाषित के साथ MethodToBeCalled कॉल नहीं करते हैं। न ही प्लंकर का उदाहरण देता है। यह कोई समस्या प्रतीत नहीं होती है। दूसरे शब्दों में, यह सही दृष्टिकोण प्रतीत होता है जब आप निर्देश लिंक (एक अलग दायरे में) के मापदंडों को पास करना चाहते हैं। मैं नुकसान और myParam === अपरिभाषित के बारे में टिप्पणी को अद्यतन करने की सलाह देता हूं।
jazeee

यह "मार्को के समाधान की तुलना में इसका एक नुकसान है - पहले लोड पर theMethodToBeCalled फ़ंक्शन को myParam के साथ लागू किया जाएगा === अपरिभाषित" मेरे मामले में नहीं हो रहा है .... मुझे लगता है कि यहां कुछ निहित संदर्भ हैं
विक्टर

95

बस कुछ जानकारी को दूसरे उत्तरों में जोड़ने के लिए - &यदि आपको अलग-अलग स्कोप की जरूरत है, तो यह एक अच्छा तरीका है।

मार्को के समाधान का मुख्य नकारात्मक पक्ष यह है कि यह आपको एक तत्व पर एक अलग-अलग गुंजाइश बनाने के लिए मजबूर करता है, लेकिन आपके पास केवल एक तत्व पर उनमें से एक हो सकता है (अन्यथा आप कोणीय त्रुटि में चलेंगे: एकाधिक निर्देश [directive1, directive2) पूछ रहे हैं पृथक दायरे के लिए )

इसका मतलब तुम :

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

चूंकि मूल प्रश्न restrict:'A'दोनों स्थितियों के साथ एक निर्देश का उपयोग करता है, इसलिए यह बड़े अनुप्रयोगों में काफी बार उत्पन्न हो सकता है, और यहां एक अलग दायरे का उपयोग करना एक अच्छा अभ्यास नहीं है और अनावश्यक भी है। वास्तव में rekna का इस मामले में एक अच्छा अंतर्ज्ञान था, और लगभग यह काम कर रहा था, केवल एक ही चीज वह गलत कर रहा था $ पार्स फंक्शन को गलत कह रहा था (देखें कि यह यहाँ क्या रिटर्न देता है: https://docs.angularjs.org/api/ एनजी / सेवा / $ पार्स )।

टी एल; डॉ; फिक्स्ड प्रश्न कोड

<div my-method='theMethodToBeCalled(id)'></div>

और कोड

app.directive("myMethod",function($parse) {
  restrict:'A',
  link:function(scope,element,attrs) {
     // here you can parse any attribute (so this could as well be,
     // myDirectiveCallback or multiple ones if you need them )
     var expressionHandler = $parse(attrs.myMethod);
     $(element).on('theEvent',function( e, rowid ) {
        calculatedId = // some function called to determine id based on rowid

        // HERE: call the parsed function correctly (with scope AND params object)
        expressionHandler(scope, {id:calculatedId});
     }
  }
}

app.controller("myController",function($scope) {
   $scope.theMethodToBeCalled = function(id) { alert(id); };
}

11
+1 वास्तव में - गुंजाइश को अलग करने की कोई ज़रूरत नहीं है - बहुत क्लीनर!
दिमित्री ज़ैतसेव

क्या होगा यदि विशेषता में केवल विधि का नाम है, जैसे <div my-method = 'theMethodToBeCalled'> </ div> या इनलाइन फ़ंक्शन जैसे <div my-method = 'alert ("hi");' </ div>;
जोनाथन।

1
यदि आप इनमें से किसी भी दृष्टिकोण से परेशान हो रहे हैं, तो ध्यान रखें कि जिस विधि को कहा जा रहा है, उस दायरे में उपलब्ध होना चाहिए $parse
रागमुफिन

यह उत्तर ठीक वैसा ही है जैसा मैं +1
grimmdude

कार्यक्रम क्या है"? मैं बाल दिवस पर फ़ंक्शन को कैसे निष्पादित कर सकता हूं?
श्लोमो

88

ठीक से नहीं पता कि आप क्या करना चाहते हैं ... लेकिन फिर भी यहां एक संभव समाधान है।

स्थानीय दायरे में '&' - गुण के साथ एक क्षेत्र बनाएँ। यह "मूल क्षेत्र के संदर्भ में एक अभिव्यक्ति को निष्पादित करने का एक तरीका प्रदान करता है" ( विवरण के लिए निर्देशन दस्तावेज़ देखें)।

मैंने यह भी देखा कि आपने एक शॉर्टहैंड लिंकिंग फंक्शन का इस्तेमाल किया है और वहाँ ऑब्जेक्ट ऑब्जेक्ट्स में शेड किए गए हैं। आप ऐसा नहीं कर सकते। निर्देशात्मक-परिभाषा वस्तु को वापस करने के लिए यह अधिक स्पष्ट (imho) है। नीचे मेरा कोड देखें।

यहाँ एक कोड नमूना और एक बेला है

<div ng-app="myApp">
<div ng-controller="myController">
    <div my-method='theMethodToBeCalled'>Click me</div>
</div>
</div>

<script>

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

   app.directive("myMethod",function($parse) {
       var directiveDefinitionObject = {
         restrict: 'A',
         scope: { method:'&myMethod' },
         link: function(scope,element,attrs) {
            var expressionHandler = scope.method();
            var id = "123";

            $(element).click(function( e, rowid ) {
               expressionHandler(id);
            });
         }
       };
       return directiveDefinitionObject;
   });

   app.controller("myController",function($scope) {
      $scope.theMethodToBeCalled = function(id) { 
          alert(id); 
      };
   });

</script>

फ़ंक्शन को कॉल किया जाता है, जब मैंने $ गुंजाइश सेट किया है। आईडी = id के अंदर theMethodToBeCalled दृश्य अपडेट नहीं किया गया है। संभावित रूप से मुझे गुंजाइश के अंदर अभिव्यक्तिहैंडलर (आईडी) लपेटने की आवश्यकता है।
18

2
बहुत बढ़िया इसने मेरी समस्या का हल खोजने में मेरी मदद की। यह ध्यान देने योग्य है कि आपको केवल शीर्ष स्तर पर ऐसा करने की आवश्यकता है यदि आप निर्देशों का गहरा घोंसला कर रहे हैं। इस पर विचार करें: plnkr.co/edit/s3y67iGL12F2hDER2RNl?p=preview जहां मैं दो निर्देशों के माध्यम से विधि पास करता हूं।
ट्रीफेस

3
और यहाँ ऐसा करने का दूसरा (शायद अधिक कोणीय) तरीका है: plnkr.co/edit/r9CV9Y1RWRuse4RwFPka?p=preview
treeface

1
स्कोप अलगाव के बिना मैं इसे कैसे कर सकता हूं?
इवान लेवेस्क

3
+1 क्योंकि इस समाधान ने मुझे सिखाया कि मुझे स्कोप मेथोड () की आवश्यकता है; पहले विधि का वास्तविक संदर्भ प्राप्त करने के लिए।
साल

6

आप एक निर्देश बना सकते हैं जो कि उपयोग करके परमेस के साथ एक फ़ंक्शन कॉल निष्पादित करता है attrName: "&" जो बाहरी दायरे में अभिव्यक्ति को संदर्भित करने लिए ।

हम ng-clickनिर्देश को प्रतिस्थापित करना चाहते हैं ng-click-x:

<button ng-click-x="add(a,b)">Add</button>

अगर हमारे पास यह गुंजाइश थी:

$scope.a = 2;
$scope.b = 2;

$scope.add = function (a, b) {
  $scope.result = parseFloat(a) + parseFloat(b);
}

हम अपना निर्देश ऐसा लिख ​​सकते हैं:

angular.module("ng-click-x", [])

.directive('ngClickX', [function () {

  return {

    scope: {

      // Reference the outer scope
      fn: "&ngClickX",

    },

    restrict: "A",

    link: function(scope, elem) {

      function callFn () {
        scope.$apply(scope.fn());
      }

      elem[0].addEventListener('click', callFn);
    }
  };
}]);

यहाँ एक लाइव डेमो है: http://plnkr.co/edit/4QOGLD?p=info


2

यहाँ मेरे लिए क्या काम किया है।

निर्देश का उपयोग करके एचटीएमएल

 <tr orderitemdirective remove="vm.removeOrderItem(orderItem)" order-item="orderitem"></tr>

निर्देश की Html: orderitem.directive.html

<md-button type="submit" ng-click="remove({orderItem:orderItem})">
       (...)
</md-button>

निर्देश का दायरा:

scope: {
    orderItem: '=',
    remove: "&",

0

मेरा समाधान:

  1. बहुलक पर एक घटना बढ़ाएँ (जैसे। complete)
  2. फ़ंक्शन को नियंत्रित करने के लिए घटना को जोड़ने वाले एक निर्देश को परिभाषित करें

आदेश

/*global define */
define(['angular', './my-module'], function(angular, directives) {
    'use strict';
    directives.directive('polimerBinding', ['$compile', function($compile) {

            return {
                 restrict: 'A',
                scope: { 
                    method:'&polimerBinding'
                },
                link : function(scope, element, attrs) {
                    var el = element[0];
                    var expressionHandler = scope.method();
                    var siemEvent = attrs['polimerEvent'];
                    if (!siemEvent) {
                        siemEvent = 'complete';
                    }
                    el.addEventListener(siemEvent, function (e, options) {
                        expressionHandler(e.detail);
                    })
                }
            };
        }]);
});

पॉलिमर घटक

<dom-module id="search">

<template>
<h3>Search</h3>
<div class="input-group">

    <textarea placeholder="search by expression (eg. temperature>100)"
        rows="10" cols="100" value="{{text::input}}"></textarea>
    <p>
        <button id="button" class="btn input-group__addon">Search</button>
    </p>
</div>
</template>

 <script>
  Polymer({
    is: 'search',
            properties: {
      text: {
        type: String,
        notify: true
      },

    },
    regularSearch: function(e) {
      console.log(this.range);
      this.fire('complete', {'text': this.text});
    },
    listeners: {
        'button.click': 'regularSearch',
    }
  });
</script>

</dom-module>

पृष्ठ

 <search id="search" polimer-binding="searchData"
 siem-event="complete" range="{{range}}"></siem-search>

searchData नियंत्रण समारोह है

$scope.searchData = function(searchObject) {
                    alert('searchData '+ searchObject.text + ' ' + searchObject.range);

}

-2

यह काम करना चाहिए।

<div my-method='theMethodToBeCalled'></div>

app.directive("myMethod",function($parse) {
  restrict:'A',
  scope: {theMethodToBeCalled: "="}
  link:function(scope,element,attrs) {
     $(element).on('theEvent',function( e, rowid ) {
        id = // some function called to determine id based on rowid
        scope.theMethodToBeCalled(id);
     }
  }
}

app.controller("myController",function($scope) {
   $scope.theMethodToBeCalled = function(id) { alert(id); };
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.