ngModel Formatters i Parsers

103

Opublikowałem to samo pytanie w innej formie, ale nikt nie odpowiedział. Nie mam jasnego obrazu tego, co robią Formatters i Parsers w angular js.

Z definicji oba elementy formatujące i parsery wyglądają podobnie do mnie. Może się mylę, ponieważ jestem nowy w tym angularjs.

Definicja elementów formatujących

Tablica funkcji do wykonania jako potok przy każdej zmianie wartości modelu. Każda funkcja jest po kolei wywoływana, przekazując wartość do następnej. Służy do formatowania / konwersji wartości do wyświetlenia w sterowaniu i walidacji.

Definicja parserów

Tablica funkcji do wykonania, jako potok, za każdym razem, gdy formant odczyta wartość z DOM. Każda funkcja jest po kolei wywoływana, przekazując wartość do następnej. Służy do dezynfekcji / konwersji wartości, a także walidacji. W celu walidacji parsery powinny aktualizować stan ważności za pomocą $ setValidity () i zwracać undefined dla nieprawidłowych wartości.

Pomóż mi zrozumieć obie funkcje na prostym przykładzie. Doceniona zostanie prosta ilustracja obu.

RONE
źródło
2
Elementy formatujące modyfikują wyświetlaną wartość modelu, podobnie jak wyświetlanie (123) 123-1234numeru telefonu. Parsery odczytują dane za każdym razem, gdy się one zmieniają i zwykle są używane do ustawiania stanu $ valid na wejściu. Dokumenty zawierają przykłady obu.
km6zla

Odpowiedzi:

155

Ten temat został bardzo dobrze omówiony w pokrewnym pytaniu: Jak zrobić dwukierunkowe filtrowanie w AngularJS?

Podsumowując:

  • Elementy formatujące zmieniają sposób wyświetlania wartości modelu w widoku.
  • Parsery zmieniają sposób zapisywania wartości widoków w modelu.

Oto prosty przykład oparty na przykładzie w dokumentacji interfejsu 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();
  });

Możesz to zobaczyć w akcji: 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" />

Kiedy wpiszesz nazwę w (view to model), zobaczysz, że model jest zawsze pisany małymi literami. Ale kiedy klikniesz przycisk i programowo zmienisz nazwę (model do wyświetlenia), pole wejściowe jest zawsze wielkie.

j.wittwer
źródło
2
czy istnieje sposób na ustawienie tej zmiany jako typów użytkowników? Mówisz „programowo”, ale próbuję sformatować $ viewValue, gdy użytkownik wprowadza dane wejściowe, na przykład w celu formatowania numeru karty kredytowej
iamyojimbo
3
@SavvasNicholas Jeśli się nie mylę, użyłbyś, ngModel.$setViewValue(transformedInput);aby go ustawić i ngModel.$render();wyrenderować z funkcji $ parsers.
Jacob Ensor
W moim przypadku to, co $formatterszrobić, jest natychmiast odwracane przez $validators. ; (
Mikhail Batcer,
1
FYI, wspomniany plunkr już nie istnieje
Chris Brown
1
Zauważyłem, że formater działa tylko wtedy, gdy naciśniesz przycisk, a nie, jeśli wpiszesz nazwę w polu
nuander
6

Innym zastosowaniem elementów formatujących i parserów jest przechowywanie dat w czasie UTC i wyświetlanie ich w czasie lokalnym na danych wejściowych, utworzyłem poniższą dyrektywę datepicker i filtr 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();
                });
            }
        };
    }
})();

Używa tego filtru utcToLocal, który zapewnia, że ​​data wejściowa ma prawidłowy format przed konwersją na czas lokalny.

(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 służy do konwersji dat lokalnych na daty utc.

pickadate.js jest używaną wtyczką datepicker

Jason
źródło