ngModel Форматори та парсери


103

Я розмістив те саме питання в іншій формі, але ніхто не відповів. Я не отримую чіткого уявлення про те, що роблять Форматтери та Парсери у кутових js.

За визначенням, і Форматери, і Парсери схожі на мене. Можливо, я помиляюся, так як я новачок у цій кутовій.

Визначення форматів

Масив функцій, що виконуються як конвеєр, щоразу, коли значення моделі змінюються. Кожна функція викликається, у свою чергу, передаючи значення наступному. Використовується для форматування / перетворення значень для відображення в контролі та валідації.

Визначення парсерів

Масив функцій, що виконуються як конвеєр, щоразу, коли керування зчитує значення з DOM. Кожна функція викликається, у свою чергу, передаючи значення наступному. Використовується для санітації / перетворення значення, а також для перевірки. Для перевірки парсери повинні оновити стан дійсності за допомогою $ setValidity () та повернути невизначені для недійсних значень.

Будь ласка, допоможіть мені зрозуміти обидві функції простим прикладом. Проста ілюстрація обох буде вдячна.


2
Форматори змінюють відображене значення моделі, як-от показ (123) 123-1234на номер телефону. Парсери зчитують дані щоразу, коли вони змінюються, і, як правило, використовуються для встановлення $ дійсного стану вводу. Документи мають приклади обох.
km6zla

Відповіді:


155

Ця тема дуже добре висвітлювалась у пов'язаному питанні: як зробити двосторонню фільтрацію в AngularJS?

Узагальнити:

  • Форматори змінюють спосіб відображення значень моделі у вікні перегляду.
  • Парсери змінюють спосіб збереження значень подання в моделі.

Ось простий приклад, побудований на прикладі в документації api NgModelController :

  //format text going to user (model to view)
  ngModel.$formatters.push(function(value) {
    return value.toUpperCase();
  });

  //format text from the user (view to model)
  ngModel.$parsers.push(function(value) {
    return value.toLowerCase();
  });

Ви можете побачити це в дії: http://plnkr.co/UQ5q5FxyBzIeEjRYYVGX?plnkr=legacy

<input type="button" value="set to 'misko'" ng-click="data.name='misko'"/>
<input type="button" value="set to 'MISKO'" ng-click="data.name='MISKO'"/>
<input changecase ng-model="data.name" />

Коли ви введете ім'я (вид на модель), ви побачите, що модель завжди є малі. Але, коли ви натискаєте кнопку і програматично змінюєте назву (модель для перегляду), поле введення завжди є великим.


2
чи є спосіб встановити цю зміну як тип користувача? Ви говорите "програмно", але я намагаюся дозволити формат $ viewValue форматуватись, коли користувач вводить дані, наприклад, для форматування номера кредитної картки
iamyojimbo

3
@SavvasNicholas Якщо я не помиляюся, ви б ngModel.$setViewValue(transformedInput);встановили його та вивели ngModel.$render();його з функції $ parsers.
Яків Ензор

У моєму випадку, що $formattersробити, негайно повертається $validators. ; (
Михайло Батцер

1
FYI згаданий плункр вже не існує
Кріс Браун

1
Я помічаю, що форматор працює лише, якщо натиснути кнопку, а не якщо ви введете ім'я в поле
nuander

6

Ще одне використання форматів та парсерів - це коли ви хочете зберігати дати в часі UTC та відображати їх у місцевому часі на входах, я створив для цього нижче директиву вибору дат та фільтр utcToLocal.

(function () {
    'use strict';

    angular
        .module('app')
        .directive('datepicker', Directive);

    function Directive($filter) {
        return {
            require: 'ngModel',
            link: function (scope, element, attr, ngModel) {
                element.addClass('datepicker');
                element.pickadate({ format: 'dd/mm/yyyy', editable: true });

                // convert utc date to local for display
                ngModel.$formatters.push(function (utcDate) {
                    if (!utcDate)
                        return;

                    return $filter('utcToLocal')(utcDate, 'dd/MM/yyyy');
                });

                // convert local date to utc for storage
                ngModel.$parsers.push(function (localDate) {
                    if (!localDate)
                        return;

                    return moment(localDate, 'DD/MM/YYYY').utc().toISOString();
                });
            }
        };
    }
})();

Він використовує цей фільтр utcToLocal, який гарантує, що дата введення в правильному форматі перед переходом на місцевий час.

(function () {
    'use strict';

    angular
        .module('app')
        .filter('utcToLocal', Filter);

    function Filter($filter) {
        return function (utcDateString, format) {
            if (!utcDateString) {
                return;
            }

            // append 'Z' to the date string to indicate UTC time if the timezone isn't already specified
            if (utcDateString.indexOf('Z') === -1 && utcDateString.indexOf('+') === -1) {
                utcDateString += 'Z';
            }

            return $filter('date')(utcDateString, format);
        };
    }
})();

moment.js використовується для перетворення локальних в utc дати.

pickadate.js - плагін, який використовується для вибору дати

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