Búsqueda de sitios web

javascript - AngularJS ng-click stopPropagation


Tengo un evento de clic en una fila de la tabla y en esta fila también hay un botón de eliminar con un evento de clic. Cuando hago clic en el botón de eliminar, el evento de clic en la fila también se dispara.

Aquí está mi código.

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

¿Cómo puedo evitar que se dispare el evento showUser cuando hago clic en el botón eliminar en la celda de la tabla?

Respuesta #1

La directiva ngClick (así como todas las demás directivas de eventos) crea la variable $event que está disponible en el mismo alcance. Esta variable es una referencia al objeto JS event y se puede usar para llamar a 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

Respuesta #2

Una adición a la respuesta de Stewie. En caso de que tu callback decida si la propagación debe detenerse o no, encontré útil pasar el objeto $event al callback:

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

Y luego, en la propia función de retorno de llamada, puedes decidir si la propagación del evento debe detenerse:

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

Respuesta #3

Escribí una directiva que te permite limitar las áreas donde un clic tiene efecto. Podría usarse para ciertos escenarios como este, así que en lugar de tener que lidiar con el clic caso por caso, simplemente puedes decir "los clics no saldrán de este elemento".

Lo usarías así:

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

Ten en cuenta que esto impediría todos los clics en la última celda, no solo en el botón. Si eso no es lo que deseas, quizá quieras envolver el botón así:

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

Aquí está el código de la directiva:

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

Artículos relacionados