ngModel Formatierer und Parser

103

Ich habe dieselbe Frage in unterschiedlicher Form gestellt, aber niemand hat geantwortet. Ich bekomme kein klares Bild davon, was die Formatierer und Parser in eckigen js tun.

Per Definition sehen sowohl die Formatierer als auch die Parser mir ähnlich. Vielleicht irre ich mich, da ich neu in diesem Winkel bin.

Formatierer Definition

Array von Funktionen, die als Pipeline ausgeführt werden sollen, wenn sich der Modellwert ändert. Jede Funktion wird aufgerufen und gibt den Wert an die nächste weiter. Dient zum Formatieren / Konvertieren von Werten für die Anzeige in der Steuerung und Validierung.

Parser-Definition

Array von Funktionen, die als Pipeline ausgeführt werden sollen, wenn das Steuerelement einen Wert aus dem DOM liest. Jede Funktion wird aufgerufen und gibt den Wert an die nächste weiter. Dient zum Bereinigen / Konvertieren des Werts sowie zur Validierung. Zur Validierung sollten die Parser den Gültigkeitsstatus mit $ setValidity () aktualisieren und für ungültige Werte undefiniert zurückgeben.

Bitte helfen Sie mir, beide Funktionen anhand eines einfachen Beispiels zu verstehen. Eine einfache Darstellung von beiden wird geschätzt.

RONE
quelle
2
Formatierer ändern den angezeigten Wert eines Modells, z. B. die Anzeige (123) 123-1234für eine Telefonnummer. Parser lesen die Daten bei jeder Änderung und werden normalerweise verwendet, um den $ valid-Status der Eingabe festzulegen. Die Dokumente enthalten Beispiele für beide.
km6zla

Antworten:

155

Dieses Thema wurde in einer verwandten Frage sehr gut behandelt: Wie wird in AngularJS in beide Richtungen gefiltert?

Zusammenfassen:

  • Formatierer ändern, wie Modellwerte in der Ansicht angezeigt werden.
  • Parser ändern, wie Ansichtswerte im Modell gespeichert werden.

Hier ist ein einfaches Beispiel, das auf einem Beispiel in der NgModelController-API-Dokumentation aufbaut :

  //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();
  });

Sie können es in Aktion sehen: 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" />

Wenn Sie einen Namen eingeben (Ansicht zum Modell), sehen Sie, dass das Modell immer in Kleinbuchstaben geschrieben ist. Wenn Sie jedoch auf eine Schaltfläche klicken und den Namen (Modell zum Anzeigen) programmgesteuert ändern, wird das Eingabefeld immer in Großbuchstaben angezeigt.

j.wittwer
quelle
2
Gibt es eine Möglichkeit, diese Änderung während der Benutzertypen festzulegen? Sie sagen "programmatisch", aber ich versuche, den $ viewValue zu formatieren, wenn der Benutzer die Eingabe eingibt, zum Beispiel für die Formatierung von Kreditkartennummern
iamyojimbo
3
@SavvasNicholas Wenn ich mich nicht irre, würden Sie es verwenden , um es mit der $ parsers-Funktion festzulegen ngModel.$setViewValue(transformedInput);und ngModel.$render();zu rendern.
Jacob Ensor
In meinem Fall wird das, was zu $formatterstun ist, sofort von zurückgesetzt $validators. ; (
Mikhail Batcer
1
Zu Ihrer Information, der plunkr, auf den verwiesen wird, existiert nicht mehr
Chris Brown
1
Ich
stelle
6

Eine andere Verwendung für Formatierer und Parser ist, wenn Sie Datumsangaben in UTC-Zeit speichern und bei Eingaben in Ortszeit anzeigen möchten. Dazu habe ich die folgende Datepicker-Direktive und den folgenden utcToLocal-Filter erstellt.

(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();
                });
            }
        };
    }
})();

Es verwendet diesen utcToLocal-Filter, der sicherstellt, dass das Eingabedatum im richtigen Format vorliegt, bevor es in die Ortszeit konvertiert wird.

(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 wird verwendet, um lokale in utc-Daten zu konvertieren.

pickadate.js ist das verwendete Datepicker-Plugin

Jason
quelle