Açısal JS ng-click durdurma


433

Bir tablo satırında bir tıklama olay var ve bu satırda da bir tıklama olayı ile bir silme düğmesi vardır. Sil düğmesine tıkladığımda, satırdaki Olay'a da tıklanır.

İşte kodum.

<tbody>
  <tr ng-repeat="user in users" class="repeat-animation" ng-click="showUser(user, $index)">
    <td>{{user.firstname}}</td>
    <td>{{user.lastname}}</td>
    <td>{{user.email}}</td>
    <td><button class="btn red btn-sm" ng-click="deleteUser(user.id, $index)">Delete</button></td>
  </tr>
</tbody>

showUserTablo hücresindeki sil Düğmesini tıklattığımda Olayın tetiklenmesini nasıl önleyebilirim ?

Yanıtlar:


801

ngClick yönergesi (diğer tüm olay yönergelerinin yanı sıra) $eventaynı kapsamda kullanılabilen değişken oluşturur . Bu değişken JS eventnesnesine bir referanstır ve çağrı yapmak için kullanılabilir stopPropagation():

<table>
  <tr ng-repeat="user in users" ng-click="showUser(user)">
    <td>{{user.firstname}}</td>
    <td>{{user.lastname}}</td>
    <td>
      <button class="btn" ng-click="deleteUser(user.id, $index); $event.stopPropagation();">
        Delete
      </button>
    </td>              
  </tr>
</table>

PLUNKER


2
Bu kontrolör kodu - $ scope. $ Olay kullanılabilir olup olmadığını anlayamadım. Herhangi bir fikir?
user1338062

93
@event nesne ng tıklama direktifi içinde oluşturulan ve senin için geçmek sizin için kullanılabilir olan ng-clickişleyici işlevi: ng-click="deleteUser(user.id, $event)".
Stewie

6
Teşekkürler, biraz düşündüm, ama hala kokuyor sanırım :)
user1338062

2
Bunun gibi birden fazla ifade yürütmenin bir antipattern olduğunu düşünüyorum. Neden $ event'i deleteUser () ve sonra stopPropagation () öğelerini bu işlevin içinde üçüncü bir argüman olarak iletmiyorsunuz?
djheru

18
Ben de eklemek zorunda kaldı $event.preventDefault(), aksi takdirde çağrı $event.stopPropagation()düğmesini tıklarken beni uygulamanın köküne yönlendiriyordu.
destY

124

Stewie'nin cevabına ek olarak. Geri aramanızın yayılmanın durdurulup durdurulmayacağına karar vermesi durumunda, $eventnesneyi geri aramaya geçirmeyi yararlı buldum :

<div ng-click="parentHandler($event)">
  <div ng-click="childHandler($event)">
  </div>
</div>

Ve sonra geri aramanın kendisinde, olayın yayılmasının durdurulması gerekip gerekmediğine karar verebilirsiniz:

$scope.childHandler = function ($event) {
  if (wanna_stop_it()) {
    $event.stopPropagation();
  }
  ...
};

10
Bu, html özelliğinde birden fazla ifade yürütmekten daha zariftir, teşekkürler
Eason

3
'$ Event' bağımsız değişkenini html ng-click yönergesine koymayı unutmayın. İlk başta tökezledim.
ThinkBonobo

1
Derhal durmak için $ event.stopImmediatePropagation () kullanın
Edgar Chavolla

Çok basit, ama göz ardı edildi. Seçilen cevaba bakıyordum ve "gerçekten mi? BU çirkin?" Diye düşünüyordum. Parametre olarak geçmeyi bile fark etmedim. Gerçekten hoş.
tfrascaroli

10

Bir tıklamanın etkili olduğu alanları sınırlamanızı sağlayan bir yönerge yazdım. Bunun gibi belirli senaryolar için kullanılabilir, bu nedenle duruma göre tıklamayla uğraşmak yerine "tıklamalar bu öğeden çıkmayacak" diyebilirsiniz.

Bunu şöyle kullanırsınız:

<table>
  <tr ng-repeat="user in users" ng-click="showUser(user)">
    <td>{{user.firstname}}</td>
    <td>{{user.lastname}}</td>
    <td isolate-click>
      <button class="btn" ng-click="deleteUser(user.id, $index);">
        Delete
      </button>
    </td>              
  </tr>
</table>

Bunun yalnızca düğme için değil, son hücredeki tüm tıklamaları önleyeceğini unutmayın. İstediğiniz bu değilse düğmeyi şu şekilde sarmak isteyebilirsiniz:

<span isolate-click>
    <button class="btn" ng-click="deleteUser(user.id, $index);">
        Delete
    </button>
</span>

Direktifin kodu şöyledir:

angular.module('awesome', []).directive('isolateClick', function() {
    return {
        link: function(scope, elem) {
            elem.on('click', function(e){
                e.stopPropagation();
            });
        }
   };
});

Güzel! ngClickAsla zaten ele alınmış bir olayı yaymak istemediğim için direktifinizi yeniden adlandırdım .
maaartinus

1
Buna dikkat et. Diğer bazı eklentiler aslında bu tıklamaları dinlemek isteyebilir. Dış tıklama sırasında kapanan araç ipuçları kullanırsanız, dış tıklamalar gövdeye yayılmadığından hiçbir zaman kapanmayabilirler.
Jens

Bu iyi bir nokta, ama bu problem direktifinizde de olur. Belki de sadece ignoreNgClick=trueetkinliğe benzer bir özellik eklemeli ve onu ele almalıyım ... bir şekilde. İdeal olarak, orijinal ngClickdirektifte, ancak değiştirilmesi kirli görünüyor.
maaartinus

Evet, bu yüzden gerçekten ihtiyaç duymadıkça bu yönergeyi kullanmam. Bir kez bile bu nedenle tıklama yayılım devam etmek için başka bir yönerge yapmak zorunda kaldı. Bir izolat-tıklama direktifim vardı, sonra birkaç ebeveyn daha devam et-direktifim vardı. Bu şekilde, tıklama yalnızca orta öğeler için atlandı.
Jens

1

Benim gibi bir yönerge kullanmanız durumunda, örneğin herhangi bir model veya koleksiyondaki bir özniteliği güncelledikten sonra iki veri yolu bağlayıcısına ihtiyacınız olduğunda bu şekilde çalışır:

angular.module('yourApp').directive('setSurveyInEditionMode', setSurveyInEditionMode)

function setSurveyInEditionMode() {
  return {
    restrict: 'A',
    link: function(scope, element, $attributes) {
      element.on('click', function(event){
        event.stopPropagation();
        // In order to work with stopPropagation and two data way binding
        // if you don't use scope.$apply in my case the model is not updated in the view when I click on the element that has my directive
        scope.$apply(function () {
          scope.mySurvey.inEditionMode = true;
          console.log('inside the directive')
        });
      });
    }
  }
}

Şimdi, herhangi bir düğme, bağlantı, div vb.

<button set-survey-in-edition-mode >Edit survey</button>

-14
<ul class="col col-double clearfix">
 <li class="col__item" ng-repeat="location in searchLocations">
   <label>
    <input type="checkbox" ng-click="onLocationSelectionClicked($event)" checklist-model="selectedAuctions.locations" checklist-value="location.code" checklist-change="auctionSelectionChanged()" id="{{location.code}}"> {{location.displayName}}
   </label>



$scope.onLocationSelectionClicked = function($event) {
      if($scope.limitSelectionCountTo &&         $scope.selectedAuctions.locations.length == $scope.limitSelectionCountTo) {
         $event.currentTarget.checked=false;
      }
   };


7
Bunun neden soruyu cevapladığını düşündüğünüze dair bir açıklama ekler misiniz?
paisanco

Bu soruya bir çeşit cevap veriyor. Olayda, ilk sorunun çözdüğünden daha fazlası olan geri aramaya nasıl geçileceğini gösterir.
hewstone
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.