no angularjs como acessar o elemento que disparou o evento?

93

Eu uso Bootstrap e AngularJS em meu aplicativo da web. Estou tendo alguma dificuldade em fazer os dois funcionarem juntos.

Eu tenho um elemento, que tem o atributo data-provide="typeahead"

<input id="searchText" ng-model="searchText" type="text"
       class="input-medium search-query" placeholder="title"
       data-provide="typeahead" ng-change="updateTypeahead()" />

E quero atualizar o data-sourceatributo quando o usuário inserir no campo. A função updateTypeaheadé disparada corretamente, mas não tenho acesso ao elemento que disparou o evento, a menos que eu use $('#searchText'), que é o jeito jQuery, não o jeito AngularJS.

Qual é a melhor maneira de fazer o AngularJS funcionar com o módulo JS de estilo antigo.

David S.
fonte

Respostas:

60
 updateTypeahead(this)

não passará o elemento DOM para a função updateTypeahead(this). Aqui thisvai se referir ao escopo. Se você deseja acessar o elemento DOM, use updateTypeahead($event). Na função de retorno de chamada, você pode obter o elemento DOM por event.target.

Observação: a função ng-change não permite passar $ event como variável.

Mahbub
fonte
65
ng-change não suporta o objeto de evento $ event sendo passado como um parâmetro.
Mark Rajcok
1
O estilo ng também parece não ter suporte.
laggingreflex
4
Também votou negativamente. Não funciona para a classe ng. $ evento ficou indefinido! <li ng-repeat="item in items" role="menuitem" ng-class="{\'selected\' : isSelected($event, item)}">
Saad Benbouzid de
4
Sim, bem, realmente não responde à pergunta, já que $ event não funciona com ng-change: /
Adrian Tombu
1
provavelmente a resposta mais
superestimada
74

A maneira Angular geral de obter acesso a um elemento que acionou um evento é escrever uma diretiva e ligar () ao evento desejado:

app.directive('myChange', function() {
  return function(scope, element) {
    element.bind('change', function() {
      alert('change on ' + element);
    });
  };
});

ou com DDO (conforme o comentário de @tpartee abaixo):

app.directive('myChange', function() {
  return { 
    link:  function link(scope, element) {
      element.bind('change', function() {
        alert('change on ' + element);
      });
    }
  }
});

A diretiva acima pode ser usada da seguinte forma:

<input id="searchText" ng-model="searchText" type="text" my-change>

Plunker .

Digite no campo de texto e, em seguida, saia / desfoque. A função de retorno de chamada de alteração será acionada. Dentro dessa função de retorno de chamada, você tem acesso element.

Algumas diretivas integradas suportam a passagem de um objeto $ event. Por exemplo, ng- * clique, ng-Mouse *. Observe que ng-change não suporta este evento.

Embora você possa obter o elemento por meio do objeto $ event:

<button ng-click="clickit($event)">Hello</button>

$scope.clickit = function(e) {
    var elem = angular.element(e.srcElement);
    ...

isso vai "profundamente contra o caminho Angular" - Misko .

Mark Rajcok
fonte
Embora sua solução funcione, ela não usa o formato DDO, o que torna muito, muito confuso descobrir como adicionar / passar o escopo para a vinculação. Não há uma maneira simples em seu exemplo de simplesmente adicionar um pouco de açúcar DDO para o escopo e isso parece tão profundamente "contra o caminho Angular" quanto passar $ evento de um clique-ng. Na verdade, na documentação oficial do Angular e nos exemplos de código, não consegui encontrar um único exemplo que seja sintaticamente semelhante ao seu (ou seja, uma diretiva retornando apenas uma função anônima sem qualquer DDO).
tpartee
@tpartee, pontos positivos. Na época em que escrevi esta resposta originalmente, os documentos angular tinham exemplos de diretivas simples que apenas retornavam uma função anônima (que é a função de link). Concordo que um DDO seria melhor atualmente. Eu atualizei a resposta.
Mark Rajcok
Acho que <button ng-click = "clickit ($ event.srcElement)"> seria melhor
Carlos ABS
1
Conforme o tempo passa, estou mais e mais convencido de que "o caminho Angular" é superarquitizado e complicado
Jacob Stamm
7

você pode ficar assim facilmente primeiro evento de gravação no elemento

ng-focus="myfunction(this)"

e em seu arquivo js como abaixo

$scope.myfunction= function (msg, $event) {
    var el = event.target
    console.log(el);
}

Eu também usei.


fonte
8
isso retorna o escopo, portanto, não funcionará conforme o esperado.
vdclouis
1
Isso não resolve o problema do OP. Claro, isso permite que uma função saiba quem é a chamada, mas isso não tem relação com a chamada ng-change e não há conexão entre as duas. O que o OP precisa é ser capaz de fazer referência ao elemento que disparou o evento ng-change dentro da chamada de função que ele faz.
tpartee
Isso funciona adicionando os atributos (digamos, id): alert (event.target.id).
Weihui Guo
2

Existe uma solução usando $ element no controlador se você não quiser criar outra diretiva para este problema:

appControllers.controller('YourCtrl', ['$scope', '$timeout', '$element',
        function($scope, $timeout, $element) {

    $scope.updateTypeahead = function() {
       // ... some logic here
       $timeout(function() {
           $element[0].getElementsByClassName('search-query')[0].focus();
           // if you have unique id you can use $window instead of $element:
           // $window.document.getElementById('searchText').focus();
       });
    }
}]);

E isso funcionará com ng-change :

<input id="searchText" type="text" class="search-query" ng-change="updateTypeahead()" ng-model="searchText" />
Tomasz Górka
fonte
0

se você quiser o valor do modelo ng, pode escrever assim no evento disparado: $ scope.searchText

Dylan
fonte
0

Não tenho certeza de qual versão você tinha, mas essa pergunta foi feita há muito tempo. Atualmente com o Angular 1.5, posso usar o ng-keypressevento e a debouncefunção do Lodash para emular um comportamento semelhante como ng-change, para que eu possa capturar o $ event

<input type="text" ng-keypress="edit($event)" ng-model="myModel">

$ scope.edit = _.debounce (function ($ event) {console.log ("$ event", $ event)}, 800)

Telvin Nguyen
fonte
-2

Para passar o elemento de origem no Angular 5:

<input #myInput type="text" (change)="someFunction(myInput)">

Jaspe
fonte
1
a pergunta é para angularjs (1)
Mizanur Rahman Mojumder