Wie kann man in anglejs auf das Element zugreifen, das das Ereignis ausgelöst hat?

93

Ich verwende sowohl Bootstrap als auch AngularJS in meiner Web-App. Ich habe einige Schwierigkeiten, die beiden zusammenzubringen.

Ich habe ein Element, das das Attribut hat data-provide="typeahead"

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

Und ich möchte das data-sourceAttribut aktualisieren , wenn der Benutzer in das Feld eingibt. Die Funktion updateTypeaheadwird korrekt ausgelöst, aber ich habe keinen Zugriff auf das Element, das das Ereignis ausgelöst hat, es sei denn, ich verwende $('#searchText')den jQuery-Weg, nicht den AngularJS-Weg.

Was ist der beste Weg, um AngularJS dazu zu bringen, mit JS-Modulen alten Stils zu arbeiten?

David S.
quelle

Antworten:

60
 updateTypeahead(this)

Übergibt das DOM-Element nicht an die Funktion updateTypeahead(this). Hier thiswird auf den Umfang verwiesen. Wenn Sie auf das DOM-Element zugreifen möchten, verwenden Sie updateTypeahead($event). In der Rückruffunktion können Sie das DOM-Element von abrufen event.target.

Bitte beachten Sie: Mit der ng-change-Funktion kann $ event nicht als Variable übergeben werden.

Mahbub
quelle
65
ng-change unterstützt nicht, dass das Ereignisobjekt $ event als Parameter übergeben wird.
Mark Rajcok
1
ng-style unterstützt anscheinend auch nicht.
Laggingreflex
4
Auch herabgestimmt. Funktioniert nicht für die ng-Klasse. $ event wurde undefiniert! <li ng-repeat="item in items" role="menuitem" ng-class="{\'selected\' : isSelected($event, item)}">
Saad Benbouzid
4
Ja gut, beantwortet die Frage nicht wirklich, da $ event nicht mit ng-change funktioniert: /
Adrian Tombu
1
wahrscheinlich die am meisten überbewertete Antwort, die jemals auf SO gesehen wurde
MatteoSp
74

Der allgemeine Angular-Weg, um Zugriff auf ein Element zu erhalten, das ein Ereignis ausgelöst hat, besteht darin, eine Direktive zu schreiben und () an das gewünschte Ereignis zu binden:

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

oder mit DDO (gemäß dem Kommentar von @ tpartee unten):

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

Die obige Richtlinie kann wie folgt verwendet werden:

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

Plunker .

Geben Sie in das Textfeld ein und lassen Sie / unscharf. Die Rückruffunktion wird ausgelöst. Innerhalb dieser Rückruffunktion haben Sie Zugriff auf element.

Einige integrierte Anweisungen unterstützen die Übergabe eines $ event-Objekts. ZB ng- * click, ng-Mouse *. Beachten Sie, dass ng-change dieses Ereignis nicht unterstützt.

Obwohl Sie das Element über das $ event-Objekt erhalten können:

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

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

das geht "tief gegen den Winkelweg" - Misko .

Mark Rajcok
quelle
Während Ihre Lösung funktioniert, verwendet sie kein DDO-Format, was es sehr, sehr verwirrend macht, herauszufinden, wie der Bindung ein Bereich hinzugefügt / übergeben wird. Es gibt keinen einfachen Weg aus Ihrem Beispiel, einfach etwas DDO-Zucker für das Scoping hinzuzufügen, und das scheint genauso tief "gegen den Angular-Weg" zu sein, als würde man das $ -Ereignis mit einem Klick übergeben. Tatsächlich konnte ich in der offiziellen Angular-Dokumentation und in den Codebeispielen kein einziges Beispiel finden, das syntaktisch Ihrem ähnlich ist (dh eine Direktive, die nur eine anonyme Funktion ohne DDO zurückgibt).
tpartee
@tpartee, gute Punkte. Als ich diese Antwort ursprünglich schrieb, hatten die eckigen Dokumente Beispiele für einfache Anweisungen, die gerade eine anonyme Funktion (die Link-Funktion) zurückgaben. Ich bin damit einverstanden, dass ein DDO heutzutage besser wäre. Ich habe die Antwort aktualisiert.
Mark Rajcok
Ich denke, <button ng-click = "clickit ($ event.srcElement)"> wäre besser
Carlos ABS
1
Mit der Zeit bin ich immer mehr davon überzeugt, dass "der
Jacob Stamm
7

Sie können leicht wie dieses erste Schreibereignis auf Element bekommen

ng-focus="myfunction(this)"

und in Ihrer js-Datei wie unten

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

Ich habe es auch benutzt.


quelle
8
Dadurch wird der Gültigkeitsbereich zurückgegeben, sodass dies nicht wie erwartet funktioniert.
Vdclouis
1
Dies löst das Problem des OP überhaupt nicht. Sicher, es lässt eine Funktion wissen, wer der Angerufene ist, aber das hat keinen Einfluss auf den Aufruf von ng-change und es gibt keine Verbindung zwischen den beiden. Das OP muss in der Lage sein, auf das Element zu verweisen, das das ng-change-Ereignis innerhalb des Funktionsaufrufs ausgelöst hat.
tpartee
Dies funktioniert durch Hinzufügen der Attribute (z. B. ID): alert (event.target.id).
Weihui Guo
2

Es gibt eine Lösung mit $ element im Controller, wenn Sie keine weitere Direktive für dieses Problem erstellen möchten:

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

Und das wird mit ng-change funktionieren :

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

Wenn Sie einen Modellwert möchten, können Sie im ausgelösten Ereignis wie folgt schreiben: $ scope.searchText

Dylan
quelle
0

Ich bin nicht sicher, welche Version Sie hatten, aber diese Frage wurde vor langer Zeit gestellt. Derzeit kann ich mit Angular 1.5 das ng-keypressEreignis und die debounceFunktion von Lodash verwenden , um ein ähnliches Verhalten wie zu emulieren ng-change, sodass ich das $ -Ereignis erfassen kann

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

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

Telvin Nguyen
quelle
-2

So übergeben Sie das Quellelement in Winkel 5:

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

Jaspis
quelle
1
Die Frage ist für Angularjs (1)
Mizanur Rahman Mojumder