en angularjs ¿cómo acceder al elemento que desencadenó el evento?

93

Utilizo Bootstrap y AngularJS en mi aplicación web. Tengo algunas dificultades para que los dos funcionen juntos.

Tengo un elemento, que tiene el 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()" />

Y quiero actualizar el data-sourceatributo cuando el usuario ingresa en el campo. La función updateTypeaheadse activa correctamente, pero no tengo acceso al elemento que activó el evento, a menos que utilice $('#searchText'), que es la forma jQuery, no la forma AngularJS.

¿Cuál es la mejor manera de hacer que AngularJS funcione con el módulo JS de estilo antiguo?

David S.
fuente

Respuestas:

60
 updateTypeahead(this)

no pasará el elemento DOM a la función updateTypeahead(this). Aquí thishará referencia al alcance. Si desea acceder al elemento DOM, use updateTypeahead($event). En la función de devolución de llamada, puede obtener el elemento DOM por event.target.

Tenga en cuenta: la función ng-change no permite pasar $ event como variable.

Mahbub
fuente
65
ng-change no admite que el objeto de evento $ event se pase como parámetro.
Mark Rajcok
1
ng-style no es compatible tampoco parece.
laggingreflex
4
También votó en contra. No funciona para ng-class. $ evento no está definido! <li ng-repeat="item in items" role="menuitem" ng-class="{\'selected\' : isSelected($event, item)}">
Saad Benbouzid
4
Sí, bueno, realmente no responde la pregunta, ya que $ event no funciona con ng-change: /
Adrian Tombu
1
probablemente la respuesta más sobrevalorada jamás vista en SO
MatteoSp
74

La forma angular general de obtener acceso a un elemento que desencadenó un evento es escribir una directiva y bind () al evento deseado:

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

o con DDO (según el comentario de @ tpartee a continuación):

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

La directiva anterior se puede utilizar de la siguiente manera:

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

Plunker .

Escribe en el campo de texto, luego deja / difumina. Se activará la función de devolución de llamada de cambio. Dentro de esa función de devolución de llamada, tiene acceso a element.

Algunas directivas integradas admiten pasar un objeto $ event. Por ejemplo, ng- * clic, ng-Mouse *. Tenga en cuenta que ng-change no admite este evento.

Aunque puede obtener el elemento a través del objeto $ event:

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

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

esto va "profundamente en contra de la forma Angular" - Misko .

Mark Rajcok
fuente
Si bien su solución funciona, no usa el formato DDO, lo que hace que sea muy, muy confuso descubrir cómo agregar / pasar alcance al enlace. No hay una manera simple en su ejemplo de simplemente agregar algo de azúcar DDO para el alcance y eso parece tan profundamente "en contra de la forma Angular" como pasar $ event desde un ng-click. De hecho, en la documentación oficial de Angular y los ejemplos de código, no pude encontrar un solo ejemplo que sea sintácticamente similar al suyo (es decir, una directiva que devuelve solo una función anónima sin ningún DDO).
tpartee
@tpartee, buenos puntos. Cuando escribí originalmente esta respuesta, los documentos angulares tenían ejemplos de directivas simples que solo devolvían una función anónima (que es la función de enlace). Estoy de acuerdo en que un DDO sería mejor en estos días. Actualicé la respuesta.
Mark Rajcok
Creo que <button ng-click = "clickit ($ event.srcElement)"> sería mejor
Carlos ABS
1
A medida que pasa el tiempo, estoy cada vez más convencido de que "la forma angular" está sobrearquitectura y es demasiado complicada
Jacob Stamm
7

puede obtener fácilmente como este primer evento de escritura en el elemento

ng-focus="myfunction(this)"

y en su archivo js como a continuación

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

Yo también lo he usado.


fuente
8
esto devuelve el alcance, por lo que no funcionará como se esperaba.
vdclouis
1
Esto no resuelve en absoluto el problema del OP. Claro que le permite a una función saber quién es el llamado, pero eso no tiene relación con la llamada ng-change y no hay conexión entre los dos. Lo que necesita el OP es poder hacer referencia al elemento que desencadenó el evento ng-change dentro de la llamada de función que realiza.
tpartee
Esto funciona agregando los atributos (digamos, id): alert (event.target.id).
Weihui Guo
2

Hay una solución que usa $ element en el controlador si no desea crear otra directiva 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();
       });
    }
}]);

Y esto funcionará con ng-change :

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

si desea un valor de modelo ng, si puede escribir así en el evento desencadenado: $ scope.searchText

Dylan
fuente
0

No estoy seguro de qué versión tenías, pero esta pregunta se hizo hace mucho tiempo. Actualmente con Angular 1.5, puedo usar el ng-keypressevento y la debouncefunción de Lodash para emular un comportamiento similar ng-change, así puedo capturar el evento $

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

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

Telvin Nguyen
fuente
-2

Para pasar el elemento fuente en Angular 5:

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

Jaspe
fuente
1
la pregunta es para angularjs (1)
Mizanur Rahman Mojumder