it-swarm.com.de

AngularJS ng-click stopPropagation

Ich habe ein Klickereignis in einer Tabellenzeile und in dieser Zeile gibt es auch einen Löschknopf mit einem Klickereignis. Wenn ich auf die Schaltfläche "Löschen" klicke, wird auch das Klickereignis in der Zeile ausgelöst.

Hier ist mein Code.

<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>

Wie kann ich verhindern, dass das Ereignis showUser ausgelöst wird, wenn ich in der Tabellenzelle auf die Schaltfläche zum Löschen klicke?

420
michael_knight

die Direktive ngClick (wie auch alle anderen Event-Direktiven) erzeugt die Variable $event, die im selben Bereich verfügbar ist. Diese Variable ist eine Referenz auf das Objekt JS event und kann zum Aufrufen von stopPropagation() verwendet werden:

<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

778
Stewie

Eine Ergänzung zu Stewies Antwort. Für den Fall, dass Ihr Rückruf entscheidet, ob die Weitergabe gestoppt werden soll oder nicht, fand ich es nützlich, das Objekt $event an den Rückruf zu übergeben:

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

Und dann können Sie im Rückruf selbst entscheiden, ob die Weitergabe des Ereignisses gestoppt werden soll:

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

Ich habe eine Direktive geschrieben, mit der Sie die Bereiche einschränken können, in denen ein Klick wirkt. Es könnte für bestimmte Szenarien wie dieses verwendet werden. Anstatt sich also mit dem Klicken von Fall zu Fall befassen zu müssen, können Sie einfach sagen, dass "Klicks nicht aus diesem Element herauskommen".

Du würdest es so benutzen:

<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>

Beachten Sie, dass dadurch nicht nur die Schaltfläche, sondern alle Klicks auf die letzte Zelle verhindert werden. Wenn Sie dies nicht möchten, können Sie die Schaltfläche folgendermaßen umbrechen:

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

Hier ist der Code der Direktive:

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

Wenn Sie eine Direktive wie mich verwenden, funktioniert dies, wenn Sie die Zwei-Daten-Weg-Bindung benötigen, zum Beispiel nach dem Aktualisieren eines Attributs in einem Modell oder einer Sammlung:

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')
        });
      });
    }
  }
}

Jetzt können Sie es ganz einfach in allen Schaltflächen, Links, Divs usw. verwenden:

<button set-survey-in-edition-mode >Edit survey</button>
1
heriberto perez