в angularjs, как получить доступ к элементу, который вызвал событие?


93

Я использую в своем веб-приложении как Bootstrap, так и AngularJS. Мне трудно заставить этих двоих работать вместе.

У меня есть элемент с атрибутом data-provide="typeahead"

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

И я хочу обновить data-sourceатрибут, когда пользователь вводит данные в поле. Функция updateTypeaheadзапускается правильно, но у меня нет доступа к элементу, вызвавшему событие, если я не использую $('#searchText')способ jQuery, а не способ AngularJS.

Как лучше всего заставить AngularJS работать с JS-модулем старого стиля?

Ответы:


60
 updateTypeahead(this)

не будет передавать элемент DOM функции updateTypeahead(this). Здесь thisбудет ссылка на область применения. Если вы хотите получить доступ к элементу DOM, используйте updateTypeahead($event). В функции обратного вызова вы можете получить элемент DOM с помощью event.target.

Обратите внимание: функция ng-change не позволяет передавать событие $ как переменную.


65
ng-change не поддерживает передачу объекта события $ event в качестве параметра.
Марк Райкок

1
ng-style тоже не поддерживает.
laggingreflex 08

4
Также проголосовали против. Не работает для ng-class. $ событие не определено! <li ng-repeat="item in items" role="menuitem" ng-class="{\'selected\' : isSelected($event, item)}">
Саад Бенбузид

4
Да ладно, на самом деле не отвечает на вопрос, так как событие $ не работает с ng-change: /
Адриан Томбу

1
вероятно, самый переоцененный ответ, который когда-либо видели на SO
MatteoSp

74

Общий способ Angular получить доступ к элементу, вызвавшему событие, - это написать директиву и привязать () к желаемому событию:

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

или с DDO (согласно комментарию @ tpartee ниже):

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

Вышеуказанная директива может использоваться следующим образом:

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

Plunker .

Введите текст в текстовое поле, затем оставьте / размыть. Сработает функция обратного вызова изменения. Внутри этой функции обратного вызова у вас есть доступ к element.

Некоторые встроенные директивы поддерживают передачу объекта $ event. Например, ng- * click, ng-Mouse *. Обратите внимание, что ng-change не поддерживает это событие.

Хотя вы можете получить элемент через объект $ event:

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

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

это идет "глубоко против Angular" - Миско .


Хотя ваше решение вроде как работает, оно не использует формат DDO, что очень и очень затрудняет понимание того, как добавить / передать область действия привязке. В вашем примере нет простого способа просто добавить немного DDO-сахара для определения области видимости, и это кажется столь же глубоко «противоречащим Angular», как передача события $ из ng-click. Фактически, в официальной документации Angular и примерах кода я не нашел ни одного примера, синтаксически похожего на ваш (т.е. директивы, возвращающей только анонимную функцию без какого-либо DDO).
tpartee

@tpartee, хорошие моменты. Когда я изначально писал этот ответ, в документах angular были примеры простых директив, которые только что возвращали анонимную функцию (которая является функцией ссылки). Я согласен, что в наши дни DDO было бы лучше. Я обновил ответ.
Марк Райкок

Я думаю, что <button ng-click = "clickit ($ event.srcElement)"> было бы лучше
Карлос АБС

1
Со временем я все больше и больше убеждаюсь в том, что «путь Angular» чрезмерно
Джейкоб

7

вы можете легко получить это первое событие записи в элементе

ng-focus="myfunction(this)"

и в вашем js файле, как показано ниже

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

Я тоже его использовал.


8
это возвращает область видимости, поэтому это не будет работать должным образом.
vdclouis

1
Это вообще не решает проблему OP. Конечно, это позволяет одной функции узнать, кто вызван, но это не имеет отношения к вызову ng-change, и между ними нет связи. Что нужно OP, так это иметь возможность ссылаться на элемент, который инициировал событие ng-change внутри вызываемой им функции.
участник

Это работает путем добавления атрибутов (скажем, id): alert (event.target.id).
Weihui Guo

2

Если вы не хотите создавать другую директиву для этой проблемы, есть решение, использующее $ element в контроллере:

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

И это будет работать с ng-change :

<input id="searchText" type="text" class="search-query" ng-change="updateTypeahead()" ng-model="searchText" />

0

если вы хотите значение ng-модели, если вы можете написать так в инициированном событии: $ scope.searchText


0

Не знаю, какая у вас была версия, но этот вопрос задавали давно. В настоящее время с Angular 1.5 я могу использовать ng-keypressсобытие и debounceфункцию из Lodash для имитации аналогичного поведения, например ng-change, чтобы я мог захватить событие $

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

$ scope.edit = _.debounce (функция ($ event) {console.log ("$ event", $ event)}, 800)


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.