Angularjs: input [tekst] ngChange uruchamia się podczas zmiany wartości


92

ngChange odpala, gdy wartość się zmienia (ngChange nie są podobne do klasycznego zdarzenia onChange). Jak mogę powiązać klasyczne zdarzenie onChange z angularjs, które będzie uruchamiane tylko wtedy, gdy zawartość zostanie zatwierdzona?

Aktualne wiązanie:

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

Po prostu szukam czegoś podobnego i przyszło mi do głowy, że możesz również rozważyć aktualizację tylko wtedy, gdy pole jest prawidłowe. W ten sposób użytkownik może mieć problemy z uzyskaniem danych wejściowych w prawidłowym formacie (lub możesz im pomóc w postaci podpowiedzi i filtrów), a następnie możesz nagrodzić go aktualizacją, gdy zrobi to dobrze!
Steve Black

Znacznie bardziej elastyczne rozwiązanie, które pozwala określić zdarzenie do użycia (nie tylko rozmycie) i inne właściwości, powinno wkrótce zostać wbudowane w kąt: github.com/angular/angular.js/pull/2129
wired_in

Odpowiedzi:


96

W tym poście przedstawiono przykład dyrektywy, która opóźnia zmiany modelu na dane wejściowe do momentu uruchomienia zdarzenia rozmycia .

Oto skrzypce, które pokazują zmianę ng działającą z nową dyrektywą ng-model-on-blur. Zwróć uwagę, że jest to niewielka modyfikacja oryginalnych skrzypiec .

Jeśli dodasz dyrektywę do swojego kodu, zmienisz swoje powiązanie na to:

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

Oto dyrektywa:

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

Uwaga: jak @wjin wspomina w komentarzach poniżej, ta funkcja jest obsługiwana bezpośrednio w Angular 1.3 (obecnie w wersji beta) przez ngModelOptions. Zobacz dokumentację, aby uzyskać więcej informacji.


1
Uwaga, elm.unbind ('input') zgłasza 'TypeError' w Internet Explorerze 8, więc inne instrukcje unbind w ogóle nie zostaną wykonane. Rozwiązałem to, przenosząc elm.unbind ('input') do osobnej linii i otoczyłem ją blokiem try / catch.
Rob Juurlink

1
Angular 1.2 ma ng-blurdyrektywę: docs.angularjs.org/api/ng.directive:ngBlur
JJ Zabkar

5
Wykonałem ten kod, ale musiałem ustawić priorytet dyrektywy (tj. Priorytet: 100). Używam Angular 1.2.10. Domyślam się, że dyrektywa ngModelOnblur działała przed dyrektywą ngModel, więc nie było jeszcze nic do rozwiązania. Ta strona sprawia, że ​​wydaje się, że w przyszłości może być wbudowane rozwiązanie tego problemu
Alan West

4
UWAGA Przynajmniej w kątowym 1.3 ta funkcjonalność jest obsługiwana w domyślnej implementacji poprzez ng-model-options="{ updateOn: 'default blur' }"Zobacz dokumentację
wjin

2
@RobJuurlink (lub ktokolwiek inny, kto napotka błąd TypeError w IE8 podczas próby połączenia lub rozłączenia z danymi wejściowymi) - Patrząc na źródło Angulara, zobaczysz, że używają go $snifferdo określenia, czy przeglądarka obsługuje `` wejście '', a jeśli nie, wracają do „keydown”. Jeśli zaktualizujesz powyższą dyrektywę, aby tylko usunąć powiązanie $sniffer.hasEvent('input')
``

33

Chodzi o ostatnie dodatki do AngularJS, które mają służyć jako przyszła odpowiedź (także na inne pytanie ).

Nowsze wersje Angulara (teraz w 1.3 beta), AngularJS natywnie obsługuje tę opcję, używając ngModelOptionsnp

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

Dokumentacja NgModelOptions

Przykład:

<input type="text" name="username"
       ng-model="user.name"
       ng-model-options="{updateOn: 'default blur', debounce: {default: 500, blur: 0} }" />

Nie działa poprawnie w wersji 1.3 beta 5, ale naprawiono w obecnej wersji głównej 2602
manikanta

Dlatego wciąż jest w wersji beta i nie można go używać w aplikacjach „rzeczywistych”, takich jak ta, którą teraz tworzę.
reaper_unique

Oto opcje ng-model-options, takie jak moduł dla Angular 1.2.x github.com/fergaldoyle/modelOptions
Fergal

8

W przypadku, gdy ktoś szuka dodatkowej obsługi klawisza „enter”, oto aktualizacja skrzypiec dostarczonych przez Gloppy

Kod do przypisywania klawiszy:

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

5

Dla każdego, kto zmaga się z IE8 (nie lubi unbind ('input'), znalazłem sposób na obejście tego.

Wprowadź $ sniffer do swojej dyrektywy i użyj:

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

IE8 uspokaja się, jeśli to zrobisz :)


lub po prostu użyj try / catch
wired_in

4

Zgodnie z moją wiedzą powinniśmy używać opcji ng-change z opcją select, aw przypadku pola tekstowego - ng-blur.


To jest poprawna odpowiedź teraz, kiedy zadawano to pytanie, najwyraźniej nie istniało.
dołu

Dziękuję bardzo ... to powinna być odpowiedź
Renjith


0

Zastąp domyślne dane wejściowe zachowanie onChange (wywołaj funkcję tylko wtedy, gdy fokus utraty kontroli i wartość zostały zmienione)

UWAGA: ngChange nie jest podobna do klasycznej imprezy onChange to wypalania zdarzenie natomiast wartość zmienia niniejszej dyrektywy Przechowuje wartość elementu, gdy robi się skupić
Na rozmywa sprawdza, czy nowa wartość uległa zmianie, a jeśli tak to odpala zdarzenie

@param {String} - nazwa funkcji, która ma zostać wywołana, gdy ma zostać uruchomiona funkcja „onChange”

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

0

Miałem dokładnie ten sam problem i to zadziałało. Dodaj ng-model-updatei ng-keyupgotowe! Oto dokumenty

 <input type="text" name="userName"
         ng-model="user.name"
         ng-change="update()"
         ng-model-options="{ updateOn: 'blur' }"
         ng-keyup="cancel($event)" />
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.