AngularJS: автоматично виявляє зміну моделі


103

Припустимо, я хотів зробити щось на кшталт автоматичного запуску якогось коду (наприклад, збереження даних на сервері) кожного разу, коли значення моделі змінюються. Є єдиний спосіб зробити це, встановивши ng-changeна кожному елементі управління щось подібне, що могло б змінити модель?

Тобто, із поглядами, все змінюється правильно, коли модель змінюється, не вимагаючи явного підключення. Чи є аналог на можливість запуску коду, який зберігається на сервері? Щось на зразок

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

як ти можеш побачити щось подібне до хребта.

Відповіді:


151

У переглядах із {{}}та / або ng-моделлю Angular встановлює $watch()ес для вас за кадром.

За замовчуванням $watchпорівнює посилання. Якщо встановити третій параметр $watchв true, Кутовий буде замість «дрібного» спостерігати об'єкт для зміни. Для масивів це означає порівняння елементів масиву, для об’єктних карт це означає перегляд властивостей. Отже, це має робити те, що ви хочете:

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

Оновлення : Angular v1.2 додав для цього новий метод, `$ watchCollection () :

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

Зауважте, що слово "мілководне" використовується для опису порівняння, а не "глибокого", оскільки посилання не дотримуються - наприклад, якщо спостережуваний об'єкт містить значення властивості, яке є посиланням на інший об'єкт, цього посилання не застосовується для порівняння інший об’єкт.


1
Ах, чудово! Чи є якась причина, що це, здається, не все так задокументовано (тобто, я не думаю, що жодне з навчальних посібників на кутовому веб-сайті згадане про встановлення $ годинника безпосередньо)? Чи є щось погане в цьому, що могло б зробити налаштування (потенційно кілька) ng-changeгаків на вхідних елементах кращою ідеєю?
Алек

12
Так, було б добре, якби в головному підручнику десь згадували $ watch. Що "погано" у цьому підході, це те, що він може зайняти багато часу, якщо ваша модель велика (кожен цикл дайвінгу - кожен натискання клавіші в полі введення - призведе до того, що ця модель буде глибоко перевірена, можливо, багаторазовою) . У такому випадку краще буде вибіркове $ watch () es або селективна ng-зміна.
Марк Райкок

8

І якщо вам потрібно стилізувати елементи форми відповідно до їх стану (модифіковані / не змінені) динамічно або перевірити, чи змінилися деякі значення насправді, ви можете використовувати наступний модуль, розроблений власноруч: https://github.com/betsol / кутовий-вхід змінено

Це додає додаткових властивостей та методів до форми та її дочірніх елементів. З його допомогою ви можете перевірити, чи містить якийсь елемент нові дані або навіть перевірити, чи вся форма містить нові неза збережені дані.

Ви можете встановити наступний годинник: $scope.$watch('myForm.modified', handler)і ваш обробник буде викликаний, якщо деякі елементи форми дійсно містять нові дані або якщо вони повернуті до початкового стану.

Також ви можете використовувати modifiedвластивості окремих елементів форми, щоб фактично зменшити кількість даних, що надсилаються на сервер за допомогою AJAX-дзвінка. Немає необхідності надсилати незмінні дані.

Як бонус, ви можете повернути форму в початковий стан за допомогою виклику до форми форми reset().

Демо демонстрацію модуля можна знайти тут: http://plnkr.co/edit/g2MDXv81OOBuGo6ORvdt?p=preview

Ура!


Чи є спосіб це перевірити в контролері. наприклад, якщо натиснути кнопку x, я можу зробити так, як якщо (myform.modified) відобразити спливаюче вікно підтвердження?
Спалах

Звичайно, просто переведіть FormController на функцію вашого контролера: <form name="myForm">, <button ng-click="vm.doSomething(myForm)">.
Слава Фомін II

дякую, це зробить щось, лише якщо форма була змінена, правда?
Спалах

Це перейде FormControllerдо doSomething()функції вашого контролера. Ви можете робити все, що завгодно, з нею всередині цієї функції, наприклад, перевірити, чи форма насправді змінена, перевіривши FormController.modifiedбульне властивість.
Слава Фомін II

Дякую! Приємна особливість
Flash
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.