dans angularjs comment accéder à l'élément qui a déclenché l'événement?

93

J'utilise à la fois Bootstrap et AngularJS dans mon application Web. J'ai de la difficulté à faire fonctionner les deux.

J'ai un élément, qui a l'attribut data-provide="typeahead"

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

Et je veux mettre à jour l' data-sourceattribut lorsque l'utilisateur entre dans le champ. La fonction updateTypeaheadest déclenchée correctement, mais je n'ai pas accès à l'élément qui a déclenché l'événement, sauf si j'utilise $('#searchText'), qui est la manière jQuery, pas la manière AngularJS.

Quelle est la meilleure façon de faire fonctionner AngularJS avec le module JS à l'ancienne.

David S.
la source

Réponses:

60
 updateTypeahead(this)

ne passera pas l'élément DOM à la fonction updateTypeahead(this). Ici thisse référera à la portée. Si vous souhaitez accéder à l'élément DOM, utilisez updateTypeahead($event). Dans la fonction de rappel, vous pouvez obtenir l'élément DOM par event.target.

Remarque: la fonction ng-change ne permet pas de passer $ event comme variable.

Mahbub
la source
65
ng-change ne prend pas en charge l'objet événement $ event passé en tant que paramètre.
Mark Rajcok
1
ng-style ne supporte pas non plus il semble.
laggingreflex
4
Voté contre. Ne fonctionne pas pour ng-class. $ event est indéfini! <li ng-repeat="item in items" role="menuitem" ng-class="{\'selected\' : isSelected($event, item)}">
Saad Benbouzid
4
Eh bien, ne répond pas vraiment à la question, car $ event ne fonctionne pas avec ng-change: /
Adrian Tombu
1
probablement la réponse la plus surestimée jamais vue sur SO
MatteoSp
74

La façon générale Angular d'accéder à un élément qui a déclenché un événement est d'écrire une directive et bind () à l'événement souhaité:

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

ou avec DDO (selon le commentaire de @ tpartee ci-dessous):

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

La directive ci-dessus peut être utilisée comme suit:

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

Plunker .

Tapez dans le champ de texte, puis laissez / floutez. La fonction de rappel de changement se déclenchera. Dans cette fonction de rappel, vous avez accès à element.

Certaines directives intégrées prennent en charge le passage d'un objet $ event. Par exemple, ng- * clic, ng-souris *. Notez que ng-change ne prend pas en charge cet événement.

Bien que vous puissiez obtenir l'élément via l'objet $ event:

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

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

cela va "profondément contre la voie angulaire" - Misko .

Mark Rajcok
la source
Bien que votre solution fonctionne en quelque sorte, elle n'utilise pas le format DDO, ce qui rend très, très déroutant pour comprendre comment ajouter / passer une portée à la liaison. Il n'y a pas de moyen simple, d'après votre exemple, d'ajouter simplement du sucre DDO pour la portée et cela semble tout aussi profondément "contre la voie angulaire" que de passer $ event à partir d'un ng-click. En fait, dans la documentation officielle Angular et les exemples de code, je n'ai pas pu trouver un seul exemple qui soit syntaxiquement similaire au vôtre (c'est-à-dire une directive ne renvoyant qu'une fonction anonyme sans DDO).
tpartee le
@tpartee, bons points. À l'époque où j'ai initialement écrit cette réponse, les documents angulaires contenaient des exemples de directives simples qui venaient de renvoyer une fonction anonyme (qui est la fonction de lien). Je suis d'accord qu'un DDO serait mieux ces jours-ci. J'ai mis à jour la réponse.
Mark Rajcok
Je pense que <button ng-click = "clickit ($ event.srcElement)"> serait mieux
Carlos ABS
1
Au fil du temps, je suis de plus en plus convaincu que "la voie angulaire" est sur-architecturée et trop compliquée
Jacob Stamm
7

vous pouvez obtenir facilement comme ce premier événement d'écriture sur l'élément

ng-focus="myfunction(this)"

et dans votre fichier js comme ci-dessous

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

Je l'ai aussi utilisé.


la source
8
cela renvoie la portée, donc cela ne fonctionnera pas comme prévu.
vdclouis
1
Cela ne résout pas du tout le problème du PO. Bien sûr, cela permet à une fonction de savoir qui est l'appelé, mais cela n'a aucune incidence sur l'appel ng-change et il n'y a aucun lien entre les deux. Ce dont l'OP a besoin, c'est de pouvoir référencer l'élément qui a déclenché l'événement ng-change dans l'appel de fonction qu'il effectue.
tpartee le
Cela fonctionne en ajoutant les attributs (par exemple, id): alert (event.target.id).
Weihui Guo
2

Il existe une solution utilisant $ element dans le contrôleur si vous ne souhaitez pas créer une autre directive pour ce problème:

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();
       });
    }
}]);

Et cela fonctionnera avec ng-change :

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

si vous voulez une valeur de ng-model, si vous pouvez écrire comme ceci dans l'événement déclenché: $ scope.searchText

Dylan
la source
0

Je ne sais pas quelle version vous aviez, mais cette question a été posée il y a longtemps. Actuellement avec Angular 1.5, je peux utiliser l' ng-keypressévénement et la debouncefonction de Lodash pour émuler un comportement similaire ng-change, afin de pouvoir capturer l'événement $

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

$ scope.edit = _.debounce (fonction ($ événement) {console.log ("$ événement", $ événement)}, 800)

Telvin Nguyen
la source
-2

Pour passer l'élément source dans Angular 5:

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

Jaspe
la source
1
la question est pour angularjs (1)
Mizanur Rahman Mojumder