AngularJS: tự động phát hiện thay đổi trong mô hình


103

Giả sử tôi muốn làm điều gì đó như tự động chạy một số mã (như lưu dữ liệu vào máy chủ) bất cứ khi nào giá trị của mô hình thay đổi. Có phải cách duy nhất để làm điều này bằng cách đặt một cái gì đó như ng-changetrên mỗi điều khiển có thể thay đổi mô hình không?

Tức là, với quan điểm, mọi thứ thay đổi ngay khi mô hình được thay đổi mà không cần phải kết nối rõ ràng bất cứ điều gì. Có cách nào để có thể chạy mã lưu vào máy chủ không? Cái gì đó như

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

như bạn có thể thấy với một cái gì đó giống như xương sống.

Câu trả lời:


151

Trong các chế độ xem với {{}}và / hoặc ng-model, Angular đang thiết lập các góc $watch()cho bạn ở hậu trường.

Theo mặc định $watchso sánh theo tham chiếu. Nếu bạn đặt tham số thứ ba $watchthành true, Angular thay vào đó sẽ "nông" theo dõi đối tượng để biết các thay đổi. Đối với mảng, điều này có nghĩa là so sánh các mục của mảng, đối với bản đồ đối tượng, điều này có nghĩa là xem các thuộc tính. Vì vậy, điều này sẽ làm những gì bạn muốn:

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

Cập nhật : Angular v1.2 đã thêm một phương thức mới cho việc này, `$ watchCollection () :

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

Lưu ý rằng từ "cạn" được sử dụng để mô tả so sánh hơn là "sâu" vì tham chiếu không được theo sau - ví dụ: nếu đối tượng được theo dõi có chứa giá trị thuộc tính là tham chiếu đến đối tượng khác, tham chiếu đó không được theo sau để so sánh đối tượng kia.


1
Tuyệt quá! Có lý do gì mà điều này dường như không phải là tất cả những gì được ghi lại (tức là, tôi không nghĩ rằng bất kỳ hướng dẫn nào trên trang web góc cạnh đề cập đến việc thiết lập $ đồng hồ trực tiếp)? Có điều gì không tốt về điều này khiến việc thiết lập (có thể có nhiều) ng-changehook trên các điều khiển đầu vào là một ý tưởng tốt hơn không?
Alec

12
Vâng, sẽ rất tuyệt nếu hướng dẫn chính đề cập đến $ watch ở đâu đó. Điều "không tốt" về cách tiếp cận này là nó có thể tốn thời gian nếu mô hình của bạn lớn (mọi chu kỳ thông báo - mỗi lần nhấn phím trong trường nhập - sẽ dẫn đến việc mô hình này được kiểm tra sâu, có thể nhiều lần) . Trong trường hợp đó, $ watch () es có chọn lọc hoặc ng-change có chọn lọc sẽ tốt hơn.
Mark Rajcok

8

Và nếu bạn cần tạo kiểu động cho các phần tử biểu mẫu của mình theo trạng thái của nó (đã sửa đổi / không sửa đổi) hoặc để kiểm tra xem một số giá trị đã thực sự thay đổi hay chưa, bạn có thể sử dụng mô-đun sau do chính tôi phát triển: https://github.com/betsol / angle-input-mod

Nó thêm các thuộc tính và phương thức bổ sung vào biểu mẫu và đó là các phần tử con. Với nó, bạn có thể kiểm tra xem một số phần tử có chứa dữ liệu mới hoặc thậm chí kiểm tra xem toàn bộ biểu mẫu có dữ liệu mới chưa được lưu hay không.

Bạn có thể thiết lập đồng hồ sau: $scope.$watch('myForm.modified', handler)và trình xử lý của bạn sẽ được gọi nếu một số phần tử biểu mẫu thực sự chứa dữ liệu mới hoặc nếu nó được đảo ngược về trạng thái ban đầu.

Ngoài ra, bạn có thể sử dụng modifiedthuộc tính của các phần tử biểu mẫu riêng lẻ để thực sự giảm lượng dữ liệu được gửi đến máy chủ thông qua lệnh gọi AJAX. Không cần phải gửi dữ liệu không thay đổi.

Như một phần thưởng, bạn có thể hoàn nguyên biểu mẫu của mình về trạng thái ban đầu thông qua reset()phương thức gọi đến biểu mẫu .

Bạn có thể tìm thấy bản demo của mô-đun tại đây: http://plnkr.co/edit/g2MDXv81OOBuGo6ORvdt?p=preview

Chúc mừng!


Có cách nào để kiểm tra điều này trong bộ điều khiển. ví dụ: nếu nhấp vào nút x, tôi có thể làm như một cửa sổ xác nhận hiển thị if (myform.modified) không?
Flash

Tất nhiên, chỉ cần chuyển FormController đến chức năng của bộ điều khiển của bạn: <form name="myForm">, <button ng-click="vm.doSomething(myForm)">.
Slava Fomin II

cảm ơn điều này sẽ làm một cái gì đó chỉ khi biểu mẫu được sửa đổi phải không?
Flash

Điều này sẽ chuyển FormControllerđến doSomething()chức năng của bộ điều khiển của bạn. Bạn có thể làm bất cứ điều gì bạn muốn với nó bên trong hàm đó, ví dụ: kiểm tra xem biểu mẫu có thực sự được sửa đổi hay không bằng cách kiểm tra thuộc tính FormController.modifiedboolean.
Slava Fomin II,

Cảm ơn! Tính năng tốt đẹp
Flash
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.