Acessando o elemento clicado em angularjs

173

Sou relativamente novo no AngularJS e suspeito que não estou entendendo um conceito. Também estou usando o Twitter Bootstrap e tenho o jQuery carregado.

Fluxo de trabalho: o usuário clica em um link de uma lista, a seção "mestre" é atualizada e o usuário clicado em ganha a classe ativa.

Marcação HTML básica:

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

Fazendo isso no jQuery:

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

Mas não consigo descobrir como integrar o Angular e o jQuery para fazer isso, porque estou usando o Angular para buscar a lista principal (no formato JSON) do servidor e atualizar uma lista na página.

Como faço para integrar isso? Parece que não consigo encontrar o elemento em que clicamos quando estou na função do controlador angular

Controlador:

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

Respostas:

283

Enquanto o AngularJS permite que você conheça um evento de clique (e, portanto, um destino dele) com a seguinte sintaxe (observe o $eventargumento da setMasterfunção; documentação aqui: http://docs.angularjs.org/api/ng.directive : ngClick ):

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

essa não é uma maneira muito angular de resolver esse problema. Com o AngularJS, o foco está na manipulação do modelo. Alguém poderia modificar um modelo e deixar o AngularJS descobrir a renderização.

A maneira AngularJS de resolver esse problema (sem usar o jQuery e sem a necessidade de passar o $eventargumento ) seria:

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

onde métodos no controlador ficariam assim:

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

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

Aqui está o jsFiddle completo: http://jsfiddle.net/pkozlowski_opensource/WXJ3p/15/

pkozlowski.opensource
fonte
198
FYI: $ event não funciona, a menos que seja aprovado na marcação: ng-click="setMaster(section, $event)"Apenas um aviso.
Ben Lesh
4
Na verdade, ele precisa ser passado para a função. Na realidade, porém, provavelmente não é a melhor ideia fazer referência a coisas específicas do dom como essa em seu controlador. Geralmente, quando $ event é usado, ele ocorre no contexto de interromper a propagação ou algo parecido: <a ng-click="doSomething(); $event.stopPropagation()">Click Just Me</a>
Ben Lesh
9
Ocorreu um problema ao usar o $ event.target porque havia um ícone dentro do meu botão. Então, às vezes o resultado desejado é o botão e, às vezes, o ícone (dependendo de onde eu cliquei). Eu usei $ event.currentTarget em vez de target e funcionou como um encanto.
lao 10/05
4
Embora usar $event.targetdessa maneira possa não ser a "maneira angular", sinto que ter uma ng-repeatlista grande com todos os itens que precisam de um ouvinte para avaliar uma alteração não é eficiente? Clicar em um elemento significa que todos os itens da lista inteira devem ser reavaliados, certo? - por que não apenas direcionar esse item $event.targetpara alternar uma classe CSS, por exemplo. O que você acha? Estou trabalhando em um aplicativo Phonegap e preciso apertar todos os ajustes de desempenho que puder.
amigos estão dizendo sobre bradley flood
13
Eu também gostaria de recomendar o uso em $event.currentTargetvez de $event.target. Se o elemento com ng-click tiver elementos filho, se o elemento filho for clicado, ele $event.targetse tornará o elemento filho. $event.currentTargetsempre segmentará o elemento com o ng-click designado.
Gene Parcellano