नेस्टेड एनजी-क्लिक कॉल के बीच घटना प्रसार को रद्द करने का सबसे अच्छा तरीका क्या है?


180

यहाँ एक उदाहरण है। मान लीजिए कि मैं बहुत सारी साइटों की तरह एक छवि ओवरले करना चाहता हूं। इसलिए जब आप एक थंबनेल पर क्लिक करते हैं, तो आपकी पूरी विंडो पर एक काला ओवरले दिखाई देता है, और छवि का एक बड़ा संस्करण इसमें केंद्रित होता है। ब्लैक ओवरले पर क्लिक करना इसे खारिज करता है; छवि पर क्लिक करने से एक फ़ंक्शन कॉल होगा जो अगली छवि दिखाता है।

HTML:

<div ng-controller="OverlayCtrl" class="overlay" ng-click="hideOverlay()">
    <img src="http://some_src" ng-click="nextImage()"/>
</div>

जावास्क्रिप्ट:

function OverlayCtrl($scope) {
    $scope.hideOverlay = function() {
        // Some code to hdie the overlay
    }
    $scope.nextImage = function() {
        // Some code to find and display the next image
    }
}

यदि आप छवि पर क्लिक करें, दोनों, समस्या यह है कि इस सेटअप के साथ nextImage()और hideOverlay()कहा जाता है। लेकिन जो मैं चाहता हूं वह केवल nextImage()कहलाने के लिए है।

मुझे पता है कि आप nextImage()फ़ंक्शन को इस तरह से पकड़ सकते हैं और रद्द कर सकते हैं :

if (window.event) {
    window.event.stopPropagation();
}

... लेकिन मैं यह जानना चाहता हूं कि क्या ऐसा करने का एक बेहतर AngularJS तरीका है जो मुझे इस स्निपेट के साथ ओवरले के अंदर तत्वों पर सभी कार्यों को उपसर्ग करने की आवश्यकता नहीं होगी।


1
return falseसमारोह के अंत में
जोनाथन डे एम।

1
मेरा मानना ​​है कि इसके लिए करने का तरीका है onclick, नहीं ng-click
माइकल Scheper

जवाबों:


193

@JosephSilber ने क्या कहा, या ng-clickकॉलबैक में $ घटना वस्तु को पास करें और इसके अंदर के प्रचार को रोकें:

<div ng-controller="OverlayCtrl" class="overlay" ng-click="hideOverlay()">
  <img src="http://some_src" ng-click="nextImage($event)"/>
</div>
$scope.nextImage = function($event) {
  $event.stopPropagation();
  // Some code to find and display the next image
}

8
$ event.preventDefault () का उपयोग करें; v> 1.5 में
कूलकबिन

3
@KoolKabin मैं Angular 1.5.8 और $ event.stopPropagation () का उपयोग कर रहा हूं जो अभी भी ठीक काम करता है। $ event.preventDefault () हालांकि काम नहीं करता है
HammerNL

1
अजीब है, क्योंकि मेरे पास विपरीत स्थिति है। stopPropagation अब काम नहीं करता है, लेकिन stopDefault () करता है। केवल अंतर यह है कि मुझे सीधे एनजी-क्लिक पर बुलाया गया है। <tr ng-click = "ctr.foo (); $ घटना ।preventDefault ()"> ..... </ tr>
MilitelloVinx

171

उपयोग करें $event.stopPropagation():

<div ng-controller="OverlayCtrl" class="overlay" ng-click="hideOverlay()">
    <img src="http://some_src" ng-click="nextImage(); $event.stopPropagation()" />
</div>

यहाँ एक डेमो है: http://plnkr.co/edit/3Pp3NFbGxy30srl8OBmQ?p ।preview


मैं ReferenceError: $event is not definedसांत्वना में मिलता हूं ।
cilphex

हां, यह करता है ... यह भी काम करता है जब मैं खरोंच से एक अलग सरल संस्करण लिखता हूं। मैं यह पता लगाने की कोशिश कर रहा हूं कि यह मेरे विकास कोड में क्या काम नहीं कर सकता है।
दुन्नो

@ cilphex - क्या आप कोणीय के अप-टू-डेट संस्करण का उपयोग कर रहे हैं?
जोसेफ सिल्बर

हां - बस समस्या मिल गई। परीक्षण करते समय मैंने $event.stopPropagation()ऐसी जगह डालने की कोशिश की जहां यह काम नहीं करता है। इसे हटाना भूल गए। इसलिए जब मैंने इसे रखा जहां यह काम करता था, तो इसे दूसरी बार कहा जा रहा था, जहां यह नहीं था। बेकार डुप्लिकेट से छुटकारा पा लिया और यह सफल है। आपकी सहायता के लिए धन्यवाद।
cilphex

101

मुझे इसके लिए एक निर्देश का उपयोग करने का विचार पसंद है:

.directive('stopEvent', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            element.bind('click', function (e) {
                e.stopPropagation();
            });
        }
    };
 });

फिर निर्देश का उपयोग करें जैसे:

<div ng-controller="OverlayCtrl" class="overlay" ng-click="hideOverlay()">
    <img src="http://some_src" ng-click="nextImage()" stop-event/>
</div>

यदि आप चाहते हैं, तो आप इस समाधान को इस तरह से अधिक सामान्य बना सकते हैं जैसे एक अलग सवाल का जवाब: https://stackoverflow.com/a/14547223/347216


2
यदि आपका तत्व गतिशील रूप से DOM से जोड़ा / हटा दिया गया है, तो अपने तत्व को '$ नष्ट' घटना के लिए देखना न भूलें ताकि आप हैंडलर को खोल सकें। जैसे, element.on ('$ नष्ट', फ़ंक्शन () {/ * यहाँ unbinding * /});
ब्रूसेसेब

है stop-eventकिसी html विशेषता? मैं इसे मोज़िला डेवलपर नेटवर्क या कहीं और नहीं ढूँढ सका।
एहतेश चौधरी

3
@ ईशेशचौधरी - "स्टॉप-इवेंट" ऊपर जेएस स्निपेट में बनाया गया नया निर्देश है। यहां निर्देशन की घोषणा करने और उपयोग करने के बारे में अधिक जानकारी देखें: docs.angularjs.org/guide/directive
डेविड

अच्छा समाधान! मैंने वास्तव में angular-eat-eventनिर्देश को बोवर पर पंजीकृत किया , जो एक समान तरीके से काम करता है!
gion_13

यह काम नहीं लगता है, निर्देश के पहले एनजी-क्लिक मूल्यांकन करता है। इसलिए मैं निर्देश को क्रियान्वित करने से रोक सकता हूं लेकिन अन्य तरीके से नहीं।
राफेल

31

कभी-कभी, यह करने के लिए सबसे अधिक समझदारी हो सकती है:

<widget ng-click="myClickHandler(); $event.stopPropagation()"/>

मैंने इसे इस तरह से करने के लिए चुना क्योंकि मैं myClickHandler()कई अन्य जगहों पर इस घटना के प्रचार को रोकना नहीं चाहता था।

ज़रूर, मैं हैंडलर फ़ंक्शन के लिए बूलियन पैरामीटर जोड़ सकता था, लेकिन stopPropagation()बस की तुलना में बहुत अधिक सार्थक है true


2
मुझे हमेशा यह संस्करण पसंद आया, ऐसा लगता है कि तत्व का नेस्टिंग उस फ़ंक्शन से संबंधित नहीं होना चाहिए जिसे मैं कॉल कर रहा
हूं

मुझे $event.stopPropagation()आंतरिक तत्वों से जोड़ना था ।
किशोर पवार

@ किशोरपावर: क्यों? क्या जिस तरह से मैंने जवाब में किया वह आपके लिए काम नहीं आया? यदि ऐसा नहीं होता है, तो यह पता लगाना हमारे लिए अच्छा होगा कि क्या यह कोणीय काम करने के तरीके में बदलाव के कारण है, या आपके कोड में कोई समस्या है।
माइकल शेपर

@MichaelScheper मैं तत्व checkboxमें लिपटा हुआ हूं div। मेरे div12 कॉलम हैं और checkbox3 कॉलम कह रहे हैं। मैं एक समारोह कॉल करने के लिए चाहता था Aके क्लिक पर divऔर समारोह Bके क्लिक पर checkbox। इसलिए जब मैं क्लिक कर रहा था, तो checkboxदोनों कार्य रद्द हो रहे थे। जब मैं इसमें शामिल ng-click="$event.stopPropagation()"होता checkboxहूं, तो मुझे केवल फंक्शन Bइनवॉइस मिला है ।
किशोर पवार

@ किशोरपाल: आह। हां, मैं यह उम्मीद करूंगा, और वास्तव में, stopPropagation()माता-पिता के तत्वों को फैलाने वाली घटना को रोकना है। मुझे यकीन नहीं है कि आप कैसे कॉल कर रहे हैं Bक्योंकि यह निर्दिष्ट नहीं है ng-click, लेकिन जवाब का मुद्दा यह है कि आप ऐसा कर सकते हैं <checkbox ng-click="B(); $event.stopPropagation()">:। आपको stopPropagation()फ़ंक्शन को शामिल नहीं करना है B
माइकल शेपर

7

यह मेरे लिए काम करता है:

<a href="" ng-click="doSomething($event)">Action</a>

this.doSomething = function($event) {
  $event.stopPropagation();
  $event.preventDefault();
};

मैं Ctrl कुंजी दबाकर या उसके बिना माउस क्लिक को संभालना चाहता था। ब्राउज़र में HTML तत्वों के चयन (और हाइलाइट) को रोकने के लिए (मेरे मामले में IE 11) जब उपयोगकर्ता Ctrl कुंजी को दबाए रखने के साथ विभिन्न मदों पर क्लिक करता है, तो मुझे एनजी-मूसडाउन इवेंट का उपयोग करना था और $ घटना के माध्यम से डिफ़ॉल्ट व्यवहार को रद्द करना था। .preventDefault ()
फोलपर

4

यदि आप इस लिंक के साथ-साथ सभी लिंक को रोकने का प्रचार नहीं करना चाहते हैं। थोड़ा और अधिक स्केलेबल।

$scope.hideOverlay( $event ){

   // only hide the overlay if we click on the actual div
   if( $event.target.className.indexOf('overlay') ) 
      // hide overlay logic

}

2
यह समाधान प्रदान किए गए उदाहरण के लिए काम करता है (जो बहुत अच्छा है!), हालांकि यह तब काम नहीं करता है जब बाहरी div में href / ng-click से पहले n या अधिक नेस्टेड तत्व होते हैं। तब जब HideOverlay () कॉलबैक को लागू किया जाता है तो लक्ष्य नेस्टेड तत्वों में से एक होता है और एनजी-क्लिक निर्देश के साथ सबसे बाहरी तत्व नहीं होता है। नेस्टेड तत्वों को गर्भ धारण करने के लिए माता-पिता को प्राप्त करने के लिए jquery का उपयोग कर सकते हैं और देख सकते हैं कि क्या पहले क्लिक करने योग्य (ए, एनजी-क्लिक, आदि) माता-पिता का ओवरले क्लास था, लेकिन यह थोड़ा बोझिल लग रहा है ...
आमिर

कंसोल.लॉग ("पोटेटोवरले" .indexOf ("ओवरले")! = -1); console.log (/ \ boverlay \ बी / g.test ( "potatooverlay"));

कोणीय आपको ऐसा करने देगा event.target.classList.indexOf('overlay') और यह चाल ठीक भी काम करेगी जब div को अन्य divs में नेस्ट किया जाता है
deltree

0

यदि आप अपने टेम्पलेट के मूल तत्व पर एनजी-क्लिक = "$ event.stopPropagation" सम्मिलित करते हैं, तो स्टॉपप्रोपोगेशन पकड़ा जाएगा क्योंकि यह पेड़ को बुलबुले बनाता है, इसलिए आपको केवल इसे अपने पूरे टेम्पलेट के लिए एक बार लिखना होगा।


0

आप एक अन्य निर्देश दर्ज कर सकते हैं ng-clickजिसके शीर्ष पर डिफ़ॉल्ट व्यवहार में संशोधन होता है ng-clickऔर घटना के प्रसार को रोक देता है। इस तरह आपको $event.stopPropagationहाथ से नहीं जोड़ना पड़ेगा ।

app.directive('ngClick', function() {
    return {
        restrict: 'A',
        compile: function($element, attr) {
            return function(scope, element, attr) {
                element.on('click', function(event) {
                    event.stopPropagation();
                });
            };
        }
    }
});

0
<div ng-click="methodName(event)"></div>

नियंत्रक उपयोग में

$scope.methodName = function(event) { 
    event.stopPropagation();
}

सबसे पहले इसे करने की विधि में घटना भेजें
दिनेश जैन

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