Angularjs: input [text] ngChange wird ausgelöst, während sich der Wert ändert

92

ngChange wird ausgelöst, während sich der Wert ändert (ngChange ähnelt nicht dem klassischen onChange-Ereignis). Wie kann ich das klassische onChange-Ereignis mit anglejs binden, das nur ausgelöst wird, wenn der Inhalt festgeschrieben wird?

Aktuelle Bindung:

<input type="text" ng-model="name" ng-change="update()" />
Kaffee Bohne
quelle
Ich habe nur nach etwas Ähnlichem gesucht und mir ist aufgefallen, dass Sie möglicherweise auch nur dann eine Aktualisierung in Betracht ziehen möchten, wenn das Feld gültig ist. Auf diese Weise kann der Benutzer Schwierigkeiten haben, die Eingabe in ein gültiges Format zu bringen (oder Sie können ihm mit Eingabeaufforderungen und Filtern helfen), und Sie können ihn dann mit einem Update belohnen, wenn er es richtig macht!
Steve Black
Eine viel flexiblere Lösung, mit der das zu verwendende Ereignis (nicht nur Unschärfe) und andere Eigenschaften angegeben werden können, sollte sehr bald in eckig integriert werden: github.com/angular/angular.js/pull/2129
wired_in

Antworten:

96

Dieser Beitrag zeigt ein Beispiel für eine Direktive, die die Modelländerungen an einer Eingabe verzögert, bis das Unschärfeereignis ausgelöst wird.

Hier ist eine Geige, die zeigt, wie ng-change mit der neuen Direktive ng-model-on-blur funktioniert. Beachten Sie, dass dies eine leichte Änderung der ursprünglichen Geige ist .

Wenn Sie die Direktive zu Ihrem Code hinzufügen, ändern Sie Ihre Bindung wie folgt:

<input type="text" ng-model="name" ng-model-onblur ng-change="update()" />

Hier ist die Richtlinie:

// override the default input to update on blur
angular.module('app', []).directive('ngModelOnblur', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        priority: 1, // needed for angular 1.2.x
        link: function(scope, elm, attr, ngModelCtrl) {
            if (attr.type === 'radio' || attr.type === 'checkbox') return;

            elm.unbind('input').unbind('keydown').unbind('change');
            elm.bind('blur', function() {
                scope.$apply(function() {
                    ngModelCtrl.$setViewValue(elm.val());
                });         
            });
        }
    };
});

Hinweis: Wie @wjin in den Kommentaren unten erwähnt, wird diese Funktion direkt in Angular 1.3 (derzeit in der Beta) über unterstützt ngModelOptions. Weitere Informationen finden Sie in den Dokumenten .

Gloopy
quelle
1
Achtung, elm.unbind ('input') löst in Internet Explorer 8 einen 'TypeError' aus, sodass die anderen Unbind-Anweisungen überhaupt nicht ausgeführt werden. Ich habe es gelöst, indem ich elm.unbind ('input') in eine separate Zeile verschoben und mit einem try / catch-Block umgeben habe.
Rob Juurlink
1
Angular 1.2 hat eine ng-blurDirektive: docs.angularjs.org/api/ng.directive:ngBlur
JJ Zabkar
5
Ich habe diesen Code zum Laufen gebracht, musste aber die Priorität der Direktive festlegen (dh Priorität: 100). Ich benutze Angular 1.2.10. Ich vermute, dass die ngModelOnblur-Direktive vor der ngModel-Direktive ausgeführt wurde, sodass noch nichts zu lösen war. Außerdem scheint es auf dieser Seite so, als gäbe es in Zukunft eine integrierte Lösung dafür: github.com/angular/angular.js/pull/1783
Alan West
4
HINWEIS Zumindest in Winkel 1.3 wird diese Funktionalität in der Standardimplementierung über ng-model-options="{ updateOn: 'default blur' }"Siehe Dokumentation
wjin
2
@RobJuurlink (oder jeder andere, der beim Versuch, an 'input' zu binden oder zu binden, auf den IE8 'TypeError' stößt) - Wenn Sie sich Angulars Quelle ansehen, werden Sie $snifferfeststellen, dass er verwendet, um festzustellen, ob der Browser 'input' unterstützt, und wenn nicht, Sie fallen auf "Keydown" zurück. Wenn Sie die obige Anweisung aktualisieren, um 'input' nur dann aufzuheben, wenn $sniffer.hasEvent('input')true zurückgegeben wird, können Sie diesen Fehler vermeiden und trotzdem in IE8 arbeiten
bvaughn
32

Hier geht es um die jüngsten Ergänzungen von AngularJS, die als zukünftige Antwort dienen sollen (auch für eine andere Frage ).

Angular neuere Versionen (jetzt in 1.3 Beta) unterstützt AngularJS nativ diese Option verwenden ngModelOptions, wie

ng-model-options="{ updateOn: 'default blur', debounce: { default: 500, blur: 0 } }"

NgModelOptions-Dokumente

Beispiel:

<input type="text" name="username"
       ng-model="user.name"
       ng-model-options="{updateOn: 'default blur', debounce: {default: 500, blur: 0} }" />
Manikanta
quelle
Es funktioniert nicht richtig in 1.3 Beta 5, aber behoben in aktuellen Master Build 2602
Manikanta
Aus diesem Grund befindet es sich noch in der Beta-Phase und kann nicht in "realen" Anwendungen wie der, die ich gerade erst baue, verwendet werden.
reaper_unique
Hier ist ein ng-Modell-Optionen wie Modul für Angular 1.2.x github.com/fergaldoyle/modelOptions
Fergal
8

Falls jemand anderes für zusätzliche suchen „enter“ keypress Unterstützung, hier ist ein Update für die Geige , bereitgestellt durch gloppy

Code für die Tastendruckbindung:

elm.bind("keydown keypress", function(event) {
    if (event.which === 13) {
        scope.$apply(function() {
            ngModelCtrl.$setViewValue(elm.val());
        });
    }
});
Bing Han
quelle
5

Für alle, die mit IE8 zu kämpfen haben (es mag das Aufheben der Bindung ('Eingabe') nicht), habe ich einen Weg gefunden, dies zu umgehen.

Fügen Sie $ sniffer in Ihre Direktive ein und verwenden Sie:

if($sniffer.hasEvent('input')){
    elm.unbind('input');
}

IE8 beruhigt sich, wenn Sie dies tun :)

Brad Barrow
quelle
oder verwenden Sie einfach try / catch
wired_in
4

Meines Wissens sollten wir ng-change mit der Auswahloption verwenden und im Textfeldfall ng-blur verwenden.

Anni
quelle
Dies ist jetzt die richtige Antwort, damals, als die Frage gestellt wurde, existierte sie anscheinend nicht.
Downhand
Vielen Dank ... das sollte die Antwort sein
Renjith
3

Wird $ scope. $ Watch nicht verwendet, um die Änderungen der Bereichsvariablen besser widerzuspiegeln?

Zahiduzzaman
quelle
1
Denkanstöße: benlesh.com/2013/10/title.html (betitelt: Sie sollten $ watch wahrscheinlich nicht in Ihren Controllern verwenden)
BenB
0

Überschreiben Sie die Standardeingabe für das Änderungsverhalten (rufen Sie die Funktion nur auf, wenn der Fokus und der Wert des Kontrollverlusts geändert wurden).

HINWEIS: ngChange ähnelt nicht dem klassischen onChange-Ereignis, das das Ereignis auslöst, während sich der Wert ändert. Diese Anweisung speichert den Wert des Elements, wenn es den Fokus erhält.
Bei Unschärfen wird geprüft, ob sich der neue Wert geändert hat, und wenn ja, wird das Ereignis ausgelöst

@param {String} - Funktionsname, der aufgerufen werden soll, wenn "onChange" ausgelöst werden soll

@example <input my-on-change = "myFunc" ng-model = "model">

angular.module('app', []).directive('myOnChange', function () { 
    return {
        restrict: 'A',
        require: 'ngModel',
        scope: {
            myOnChange: '='
        },
        link: function (scope, elm, attr) {
            if (attr.type === 'radio' || attr.type === 'checkbox') {
                return;
            }
            // store value when get focus
            elm.bind('focus', function () {
                scope.value = elm.val();

            });

            // execute the event when loose focus and value was change
            elm.bind('blur', function () {
                var currentValue = elm.val();
                if (scope.value !== currentValue) {
                    if (scope.myOnChange) {
                        scope.myOnChange();
                    }
                }
            });
        }
    };
});
user3119770
quelle
0

Ich hatte genau das gleiche Problem und das hat bei mir funktioniert. Fügen Sie hinzu ng-model-updateund ng-keyupund Sie können loslegen! Hier ist die Dokumentation

 <input type="text" name="userName"
         ng-model="user.name"
         ng-change="update()"
         ng-model-options="{ updateOn: 'blur' }"
         ng-keyup="cancel($event)" />
iMario999
quelle