w angularjs jak uzyskać dostęp do elementu, który wywołał zdarzenie?

93

W mojej aplikacji internetowej używam zarówno Bootstrap, jak i AngularJS. Mam pewne trudności ze zmobilizowaniem tych dwóch do współpracy.

Mam element, który ma atrybut data-provide="typeahead"

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

Chcę zaktualizować data-sourceatrybut, gdy użytkownik wprowadzi dane w polu. Funkcja updateTypeaheadjest wyzwalana poprawnie, ale nie mam dostępu do elementu, który wyzwolił zdarzenie, chyba że używam $('#searchText'), co jest sposobem jQuery, a nie sposobem AngularJS.

Jaki jest najlepszy sposób, aby AngularJS działał ze starym modułem JS.

David S.
źródło

Odpowiedzi:

60
 updateTypeahead(this)

nie przekaże elementu DOM do funkcji updateTypeahead(this). Tutaj thisbędzie odnosić się do zakresu. Jeśli chcesz uzyskać dostęp do elementu DOM, użyj updateTypeahead($event). W funkcji callback możesz pobrać element DOM przez event.target.

Uwaga: funkcja ng-change nie pozwala na przekazanie zdarzenia $ event jako zmiennej.

Mahbub
źródło
65
ng-change nie obsługuje przekazywania obiektu zdarzenia $ event jako parametru.
Mark Rajcok
1
ng-style też nie obsługuje.
laggingreflex
4
Głosowano też w dół. Nie działa dla klasy ng. $ wydarzenie zostało niezdefiniowane! <li ng-repeat="item in items" role="menuitem" ng-class="{\'selected\' : isSelected($event, item)}">
Saad Benbouzid,
4
No cóż, tak naprawdę nie odpowiada na pytanie, ponieważ $ event nie działa z ng-change: /
Adrian Tombu
1
prawdopodobnie najbardziej
przereklamowana
74

Ogólnym sposobem Angulara na uzyskanie dostępu do elementu, który wywołał zdarzenie, jest napisanie dyrektywy i powiązanie () z żądanym zdarzeniem:

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

lub z DDO (zgodnie z komentarzem @ tpartee poniżej):

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

Powyższa dyrektywa może być używana w następujący sposób:

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

Plunker .

Wpisz tekst w polu tekstowym, a następnie pozostaw / zamaż. Funkcja wywołania zwrotnego zmiany zostanie uruchomiona. Wewnątrz tej funkcji zwrotnej masz dostęp do element.

Niektóre dyrektywy wbudowane obsługują przekazywanie obiektu $ event. Np. Ng- * klik, ng-Mouse *. Zauważ, że ng-change nie obsługuje tego zdarzenia.

Chociaż możesz pobrać element za pośrednictwem obiektu $ event:

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

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

to idzie „głęboko pod Angular” - Misko .

Mark Rajcok
źródło
Chociaż Twoje rozwiązanie w pewnym sensie działa, nie używa formatu DDO, co sprawia, że ​​bardzo, bardzo mylące jest ustalenie, jak dodać / przekazać zakres do powiązania. Z twojego przykładu nie ma prostego sposobu, aby po prostu dodać trochę cukru DDO do określania zakresu, a to wydaje się równie głęboko „wbrew Angularowi”, jak przekazywanie zdarzenia $ z ng-click. W rzeczywistości w oficjalnej dokumentacji Angulara i przykładach kodu nie znalazłem ani jednego przykładu, który byłby podobny składniowo do twojego (tj. Dyrektywa zwracająca tylko anonimową funkcję bez żadnego DDO).
uczestnik
@tpartee, dobre punkty. Kiedy pierwotnie pisałem tę odpowiedź, dokumentacja kątowa zawierała przykłady prostych dyrektyw, które po prostu zwracały anonimową funkcję (która jest funkcją link). Zgadzam się, że DDO byłoby dziś lepsze. Zaktualizowałem odpowiedź.
Mark Rajcok
Myślę, że <button ng-click = "clickit ($ event.srcElement)"> byłoby lepsze
Carlos ABS
1
W miarę upływu czasu jestem coraz bardziej przekonany, że „Droga Angulara” jest przesadnie rozbudowana i nadmiernie skomplikowana
Jacob Stamm
7

możesz łatwo uzyskać takie pierwsze zdarzenie write na elemencie

ng-focus="myfunction(this)"

i w swoim pliku js, jak poniżej

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

Ja też go użyłem.


źródło
8
zwraca to zakres, więc nie będzie działać zgodnie z oczekiwaniami.
vdclouis,
1
To w ogóle nie rozwiązuje problemu PO. Jasne, pozwala jednej funkcji wiedzieć, kto jest wywoływany, ale nie ma to wpływu na wywołanie ng-change i nie ma połączenia między nimi. To, czego potrzebuje OP, to mieć możliwość odniesienia się do elementu, który wyzwolił zdarzenie ng-change w wywołaniu funkcji, które wywołuje.
uczestnik
Działa to poprzez dodanie atrybutów (powiedzmy, id): alert (event.target.id).
Weihui Guo
2

Istnieje rozwiązanie wykorzystujące $ element w kontrolerze, jeśli nie chcesz tworzyć kolejnej dyrektywy dla tego problemu:

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

I to zadziała z ng-change :

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

jeśli chcesz wartość modelu ng, jeśli możesz napisać w ten sposób w wyzwalanym zdarzeniu: $ scope.searchText

dylan
źródło
0

Nie jestem pewien, którą wersję miałeś, ale to pytanie zostało zadane dawno temu. Obecnie w Angular 1.5 mogę użyć ng-keypresszdarzenia i debouncefunkcji z Lodash do emulacji podobnego zachowania ng-change, dzięki czemu mogę przechwycić zdarzenie $

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

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

Telvin Nguyen
źródło
-2

Aby przekazać element źródłowy w Angular 5:

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

Jaspis
źródło
1
pytanie dotyczy angularjs (1)
Mizanur Rahman Mojumder