Accediendo al elemento cliqueado en angularjs

173

Soy relativamente nuevo en AngularJS y sospecho que no estoy captando un concepto. También estoy usando Twitter Bootstrap y tengo jQuery cargado.

Flujo de trabajo: el usuario hace clic en un enlace de una lista, la sección "maestra" se actualiza y el usuario del enlace hace clic en las ganancias de la clase activa.

Marcado HTML básico:

<ul class="list-holder" ng-controller="adminController">
   <li><a ng-click="setMaster('client')">Clients</li>
   <li><a ng-click="setMaster('employees')">Employees</li>
   <li><a ng-click="setMaster('etc')>Etc...</li>
</ul>

Haciendo esto en jQuery:

jQuery(".list-holder").on('click', 'a', function(event){
    event.preventDefault();
jQuery(".list-holder li").removeClass('active');
jQuery(this).parent('li').addClass('active');
});

Pero no puedo entender cómo integrar Angular y jQuery para lograr esto, porque estoy usando Angular para obtener la lista maestra (en forma JSON) del servidor y actualizar una lista en la página.

¿Cómo integro esto? Parece que no puedo encontrar el elemento en el que he hecho clic una vez que estoy dentro de la función del controlador angular

Controlador:

function adminController($scope)
    {    
        $scope.setMaster = function(obj)
        {
            // How do I get clicked element's parent li?
            console.log(obj);
        }
    }
R abajo
fuente

Respuestas:

283

Si bien AngularJS le permite echar mano de un evento de clic (y, por lo tanto, un objetivo) con la siguiente sintaxis (tenga en cuenta el $eventargumento de la setMasterfunción; documentación aquí: http://docs.angularjs.org/api/ng.directive : ngClick ):

function AdminController($scope) {    
  $scope.setMaster = function(obj, $event){
    console.log($event.target);
  }
}

Esta no es una forma muy angular de resolver este problema. Con AngularJS el foco está en la manipulación del modelo. Uno mutaría un modelo y dejaría que AngularJS descubriera el renderizado.

La forma AngularJS de resolver este problema (sin usar jQuery y sin la necesidad de pasar el $eventargumento ) sería:

<div ng-controller="AdminController">
    <ul class="list-holder">
        <li ng-repeat="section in sections" ng-class="{active : isSelected(section)}">
            <a ng-click="setMaster(section)">{{section.name}}</a>
        </li>
    </ul>
    <hr>
    {{selected | json}}
</div>

donde los métodos en el controlador se verían así:

$scope.setMaster = function(section) {
    $scope.selected = section;
}

$scope.isSelected = function(section) {
    return $scope.selected === section;
}

Aquí está el jsFiddle completo: http://jsfiddle.net/pkozlowski_opensource/WXJ3p/15/

pkozlowski.opensource
fuente
198
FYI: $ event no funciona a menos que se apruebe en el marcado: ng-click="setMaster(section, $event)"solo un aviso.
Ben Lesh
44
En realidad no, tiene que pasar a la función. En realidad, sin embargo, probablemente no sea la mejor idea hacer referencia a cosas específicas de dom como esta en su controlador. Generalmente cuando se usa $ event, es en el contexto de detener la propagación o similar: <a ng-click="doSomething(); $event.stopPropagation()">Click Just Me</a>
Ben Lesh
9
Tuve un problema al usar $ event.target porque tenía un icono dentro de mi botón. Entonces, a veces el resultado objetivo es el botón y, a veces, el ícono (dependiendo de dónde hice clic). Usé $ event.currentTarget en lugar de target y funcionó de maravilla.
lao
44
Si bien el uso de $event.targetesta manera puede no ser la "forma angular" ¿Siento que tener una ng-repeatlista grande con cada elemento que necesita un oyente para evaluar un cambio no es eficiente? Al hacer clic en un elemento, todos los elementos de la lista completa deben ser reevaluados, ¿verdad? - por qué no solo apuntar a ese elemento $event.targetpara alternar una clase CSS, por ejemplo. ¿Qué piensas? Estoy trabajando en una aplicación Phonegap y necesito exprimir cada ajuste de rendimiento que pueda.
Bradley Flood
13
También me gustaría recomendar usar en $event.currentTargetlugar de $event.target. Si el elemento con ng-click tiene elementos secundarios, si se hace clic $event.targeten el elemento secundario se convierte en el elemento secundario. $event.currentTargetsiempre apuntará al elemento con el ng-click designado.
Gene Parcellano