Angularjs: input [text] ngChange aktif saat nilainya berubah

92

ngChange diaktifkan saat nilainya berubah (ngChange tidak sama dengan acara onChange klasik). Bagaimana cara mengikat acara onChange klasik dengan angularjs, yang hanya akan aktif ketika konten dikomit?

Pengikatan saat ini:

<input type="text" ng-model="name" ng-change="update()" />
Kaffee Bohne
sumber
Hanya mencari sesuatu yang serupa dan terpikir oleh saya bahwa Anda mungkin juga ingin mempertimbangkan untuk memperbarui hanya jika bidang tersebut valid. Dengan begitu, pengguna dapat kesulitan mendapatkan masukan ke dalam format yang valid (atau Anda dapat membantu mereka dengan petunjuk dan filter), lalu Anda dapat menghadiahi mereka dengan pembaruan saat mereka melakukannya dengan benar!
Steve Black
Solusi yang jauh lebih fleksibel yang memungkinkan untuk menentukan acara yang akan digunakan (tidak hanya blur) dan properti lainnya harus segera dibangun ke sudut: github.com/angular/angular.js/pull/2129
wired_in

Jawaban:

96

Posting ini menunjukkan contoh arahan yang menunda perubahan model ke input sampai peristiwa blur diaktifkan.

Berikut ini biola yang menunjukkan ng-change bekerja dengan direktif ng-model-on-blur yang baru. Perhatikan bahwa ini adalah sedikit perubahan pada biola aslinya .

Jika Anda menambahkan arahan ke kode Anda, Anda akan mengubah pengikatan Anda ke ini:

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

Berikut arahannya:

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

Catatan: seperti yang @wjin sebutkan di komentar di bawah, fitur ini didukung langsung di Angular 1.3 (saat ini dalam versi beta) melalui ngModelOptions. Lihat dokumen untuk info lebih lanjut.

Gloopy
sumber
1
Perhatian, elm.unbind ('input') melontarkan 'TypeError' di Internet Explorer 8 sehingga pernyataan unbind lainnya tidak akan dijalankan sama sekali. Saya menyelesaikannya dengan memindahkan elm.unbind ('input') ke baris terpisah dan mengelilinginya dengan blok coba / tangkap.
Rob Juurlink
1
Angular 1.2 memiliki ng-blurarahan: docs.angularjs.org/api/ng.directive:ngBlur
JJ Zabkar
5
Saya membuat kode ini berfungsi, tetapi saya harus menetapkan prioritas direktif (yaitu, prioritas: 100). Saya menggunakan Angular 1.2.10. Dugaan saya adalah bahwa direktif ngModelOnblur berjalan sebelum direktif ngModel jadi belum ada yang bisa dilepaskan. Juga, halaman ini membuatnya tampak seperti mungkin ada solusi bawaan
Alan West
4
CATATAN Setidaknya dalam sudut 1.3 fungsionalitas ini didukung dalam implementasi default melalui ng-model-options="{ updateOn: 'default blur' }"Lihat dokumentasi
wjin
2
@RobJuurlink (atau siapa pun yang menemukan 'TypeError' IE8 saat mencoba mengikat atau melepaskan ikatan ke 'masukan') - Melihat sumber Angular, Anda akan melihat yang mereka gunakan $snifferuntuk menentukan apakah browser mendukung 'masukan' dan jika tidak, mereka kembali ke 'keydown'. Jika Anda memperbarui petunjuk di atas untuk hanya melepaskan 'input' jika $sniffer.hasEvent('input')mengembalikan nilai true - maka Anda dapat menghindari kesalahan itu dan masih berfungsi di IE8
bvaughn
32

Ini tentang tambahan terbaru untuk AngularJS, untuk dijadikan jawaban di masa mendatang (juga untuk pertanyaan lain ).

Versi Angular yang lebih baru (sekarang dalam 1,3 beta), AngularJS secara native mendukung opsi ini, menggunakan ngModelOptions, like

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

Dokumentasi NgModelOptions

Contoh:

<input type="text" name="username"
       ng-model="user.name"
       ng-model-options="{updateOn: 'default blur', debounce: {default: 500, blur: 0} }" />
manikanta
sumber
Ini tidak berfungsi dengan benar dalam 1,3 beta 5, tetapi diperbaiki dalam master build saat ini 2602
manikanta
Dan itulah mengapa ini masih dalam versi beta dan tidak dapat digunakan dalam aplikasi "dunia nyata" seperti yang saya bangun sekarang.
reaper_unique
Berikut adalah modul ng-model-options untuk Angular 1.2.x github.com/fergaldoyle/modelOptions
Fergal
8

Jika ada orang lain yang mencari dukungan tombol "masuk" tambahan, berikut ini pembaruan untuk biola yang disediakan oleh Gloppy

Kode untuk mengikat tombol:

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

Untuk siapa pun yang berjuang dengan IE8 (tidak suka pelepasan ('input'), saya menemukan cara untuk mengatasinya.

Masukkan $ sniffer ke dalam direktif Anda dan gunakan:

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

IE8 akan tenang jika Anda melakukan ini :)

Brad Barrow
sumber
atau cukup gunakan coba / tangkap
wired_in
4

Menurut pengetahuan saya, kita harus menggunakan ng-change dengan opsi pilih dan dalam kasus kotak teks kita harus menggunakan ng-blur.

Anni
sumber
Ini adalah jawaban yang benar sekarang, dulu ketika pertanyaan itu diajukan ternyata tidak ada.
turun tangan
Terima kasih banyak ... ini seharusnya jawabannya
Renjith
3

Bukankah menggunakan $ scope. $ Watch untuk mencerminkan perubahan variabel scope dengan lebih baik?

Zahiduzzaman
sumber
1
Makanan untuk dipikirkan: benlesh.com/2013/10/title.html (berjudul: Anda mungkin tidak boleh menggunakan $ watch di pengontrol Anda)
BenB
0

Timpa perilaku onChange input default (panggil fungsi hanya jika fokus dan nilai control loss berubah)

CATATAN: ngChange tidak mirip dengan acara onChange klasik, ngChange mengaktifkan peristiwa saat nilainya berubah Direktif ini menyimpan nilai elemen saat fokusnya
Diaburkan, ia memeriksa apakah nilai baru telah berubah dan jika demikian ia mengaktifkan peristiwa tersebut

@param {String} - nama fungsi yang akan dipanggil saat "onChange" harus diaktifkan

@example <masukan 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();
                    }
                }
            });
        }
    };
});
pengguna3119770
sumber
0

Saya memiliki masalah yang persis sama dan ini berhasil untuk saya. Tambahkan ng-model-updatedan ng-keyupAnda siap melakukannya! Ini dokumentasinya

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