AngularJS: secara otomatis mendeteksi perubahan model

103

Misalkan saya ingin melakukan sesuatu seperti menjalankan beberapa kode secara otomatis (seperti menyimpan data ke server) setiap kali nilai model berubah. Apakah satu-satunya cara untuk melakukan ini dengan menyetel sesuatu seperti ng-changepada setiap kontrol yang mungkin dapat mengubah model?

Yaitu, dengan tampilan, banyak hal berubah saat model diubah tanpa harus secara eksplisit menghubungkan apa pun. Apakah ada analogi untuk dapat menjalankan kode yang disimpan ke server? Sesuatu seperti

myModel.on('change', function() {
  $.post("/my-url", ...);
});

seperti yang mungkin Anda lihat dengan sesuatu seperti tulang punggung.

Alec
sumber

Jawaban:

151

Dalam views dengan {{}}dan / atau ng-model, Angular sedang menyiapkan $watch()untuk Anda di belakang layar.

Secara default $watchmembandingkan dengan referensi. Jika Anda menyetel parameter ketiga $watchke true, Angular akan "dangkal" mengawasi objek untuk perubahan. Untuk array ini berarti membandingkan item array, untuk peta objek ini berarti memperhatikan propertinya. Jadi ini harus melakukan apa yang Anda inginkan:

$scope.$watch('myModel', function() { ... }, true);

Pembaruan : Angular v1.2 menambahkan metode baru untuk ini, `$ watchCollection () :

$scope.$watchCollection('myModel', function() { ... });

Perhatikan bahwa kata "dangkal" digunakan untuk mendeskripsikan perbandingan daripada "dalam" karena referensi tidak diikuti - misalnya, jika objek yang diawasi berisi nilai properti yang merupakan referensi ke objek lain, referensi tersebut tidak diikuti untuk membandingkan objek lainnya.

Mark Rajcok
sumber
1
Ah, bagus! Apakah ada alasan mengapa ini tampaknya tidak semua yang didokumentasikan (yaitu, saya tidak berpikir salah satu tutorial di situs sudut disebutkan mengatur $ jam tangan secara langsung)? Apakah ada hal buruk tentang hal ini yang akan membuat pengaturan (berpotensi banyak) ng-changekait pada kontrol masukan menjadi ide yang lebih baik?
Alec
12
Ya, alangkah baiknya jika tutorial utama menyebutkan $ tonton di suatu tempat. Apa yang "buruk" tentang pendekatan ini adalah bahwa pendekatan ini dapat memakan waktu jika model Anda besar (setiap siklus intisari - setiap penekanan tombol dalam bidang masukan - akan mengakibatkan model ini diperiksa secara kotor, mungkin beberapa kali) . Dalam hal ini, $ watch () es selektif atau ng-change selektif akan lebih baik.
Mark Rajcok
8

Dan jika Anda perlu mengatur gaya elemen formulir Anda sesuai dengan keadaannya (dimodifikasi / tidak diubah) secara dinamis atau untuk menguji apakah beberapa nilai benar-benar berubah, Anda dapat menggunakan modul berikut, yang dikembangkan sendiri: https://github.com/betsol / sudut-masukan-dimodifikasi

Ia menambahkan properti dan metode tambahan ke formulir dan elemen anaknya. Dengan itu, Anda dapat menguji apakah beberapa elemen berisi data baru atau bahkan menguji apakah seluruh formulir memiliki data baru yang belum disimpan.

Anda dapat mengatur jam tangan berikut: $scope.$watch('myForm.modified', handler)dan penangan Anda akan dipanggil jika beberapa elemen formulir benar-benar berisi data baru atau jika dibalik ke keadaan awal.

Selain itu, Anda dapat menggunakan modifiedproperti elemen formulir individu untuk benar-benar mengurangi jumlah data yang dikirim ke server melalui panggilan AJAX. Tidak perlu mengirim data yang tidak diubah.

Sebagai bonus, Anda dapat mengembalikan formulir Anda ke keadaan awal melalui reset()metode panggilan ke formulir .

Anda dapat menemukan demo modul di sini: http://plnkr.co/edit/g2MDXv81OOBuGo6ORvdt?p=preview

Bersulang!

Slava Fomin II
sumber
Apakah ada cara untuk memeriksa ini di pengontrol. misalnya jika klik tombol x dapatkah saya melakukan seperti jika (myform.modified) menampilkan popup konfirmasi?
Flash
Tentu saja, cukup teruskan FormController ke fungsi pengontrol Anda: <form name="myForm">, <button ng-click="vm.doSomething(myForm)">.
Slava Fomin II
terima kasih ini akan melakukan sesuatu hanya jika formulir telah diubah kan?
Flash
Ini akan meneruskan FormControllerke doSomething()fungsi pengontrol Anda. Anda bisa melakukan apapun yang Anda inginkan dengan itu di dalam fungsi itu, misalnya memeriksa apakah form benar-benar diubah dengan memeriksa FormController.modifiedproperti boolean.
Slava Fomin II
Terima kasih! Fitur Bagus
Flash