Formateurs et analyseurs ngModel

103

J'ai posté la même question sous une forme différente, mais personne n'a répondu. Je n'obtiens pas une image claire de ce que font les formateurs et les analyseurs dans angular js.

Par définition, les formateurs et les analyseurs me ressemblent. Peut-être que je me trompe, car je suis nouveau dans ce angularjs.

Définition des formateurs

Tableau de fonctions à exécuter, sous forme de pipeline, chaque fois que la valeur du modèle change. Chaque fonction est appelée, à son tour, en passant la valeur à la suivante. Utilisé pour formater / convertir les valeurs à afficher dans le contrôle et la validation.

Définition des analyseurs

Tableau de fonctions à exécuter, en tant que pipeline, chaque fois que le contrôle lit une valeur dans le DOM. Chaque fonction est appelée, à son tour, en passant la valeur à la suivante. Utilisé pour nettoyer / convertir la valeur ainsi que pour la validation. Pour la validation, les analyseurs doivent mettre à jour l'état de validité en utilisant $ setValidity () et renvoyer undefined pour les valeurs non valides.

S'il vous plaît, aidez-moi à comprendre les deux fonctionnalités avec un exemple simple. Une simple illustration des deux sera appréciée.

RONE
la source
2
Les formateurs modifient la valeur affichée d'un modèle, comme l'affichage (123) 123-1234pour un numéro de téléphone. Les analyseurs lisent les données à chaque fois qu'elles changent et sont généralement utilisés pour définir l'état $ valide de l'entrée. Les documents ont des exemples des deux.
km6zla

Réponses:

155

Ce sujet a été très bien couvert dans une question connexe: Comment faire un filtrage bidirectionnel dans AngularJS?

Résumer:

  • Les formateurs modifient la manière dont les valeurs du modèle apparaissent dans la vue.
  • Les analyseurs modifient la manière dont les valeurs de vue seront enregistrées dans le modèle.

Voici un exemple simple, basé sur un exemple dans la documentation de l'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();
  });

Vous pouvez le voir en action: 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" />

Lorsque vous tapez un nom dans (vue du modèle), vous verrez que le modèle est toujours en minuscules. Mais, lorsque vous cliquez sur un bouton et que vous modifiez le nom par programme (modèle à afficher), le champ de saisie est toujours en majuscule.

j.wittwer
la source
2
y a-t-il un moyen de définir ce changement lorsque l'utilisateur tape? Vous dites "par programme", mais j'essaie de formater la valeur $ viewValue lorsque l'utilisateur entre dans l'entrée, par exemple pour le formatage du numéro de carte de crédit
iamyojimbo
3
@SavvasNicholas Si je ne me trompe pas, vous utiliseriez ngModel.$setViewValue(transformedInput);pour le définir et ngModel.$render();le rendre à partir de la fonction $ parsers.
Jacob Ensor
Dans mon cas, que $formattersfaire, est immédiatement inversé $validators. ; (
Mikhail Batcer
1
Pour info le plunkr référencé n'existe plus
Chris Brown
1
Je remarque que le formateur ne fonctionne que si vous appuyez sur le bouton, pas si vous tapez le nom dans le champ
nuander
6

Une autre utilisation des formateurs et des parseurs est que lorsque vous souhaitez stocker des dates à l'heure UTC et les afficher à l'heure locale sur les entrées, j'ai créé la directive datepicker ci-dessous et le filtre utcToLocal pour cela.

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

Il utilise ce filtre utcToLocal qui garantit que la date d'entrée est dans le format correct avant la conversion en heure locale.

(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 est utilisé pour convertir les dates locales en dates utc.

pickadate.js est le plugin datepicker utilisé

Jason
la source