Formateadores y analizadores ngModel

103

Publiqué la misma pregunta en una forma diferente, pero nadie respondió. No obtengo una imagen clara de lo que hacen los formateadores y analizadores en js angular.

Por definición, tanto los Formateadores como los Analizadores se parecen a mí. Tal vez me equivoque, ya que soy nuevo en este angularjs.

Definición de formateadores

Matriz de funciones para ejecutar, como canalización, siempre que cambie el valor del modelo. Cada función se llama, a su vez, pasando el valor a la siguiente. Se utiliza para formatear / convertir valores para mostrarlos en el control y la validación.

Definición de analizadores

Matriz de funciones para ejecutar, como canalización, siempre que el control lea valor del DOM. Cada función se llama, a su vez, pasando el valor a la siguiente. Se utiliza para desinfectar / convertir el valor y la validación. Para la validación, los analizadores deben actualizar el estado de validez usando $ setValidity () y devolver undefined para valores no válidos.

Ayúdame a comprender ambas funciones con un ejemplo sencillo. Se apreciará una simple ilustración de ambos.

RONE
fuente
2
Los formateadores modifican el valor mostrado de un modelo, como mostrar (123) 123-1234un número de teléfono. Los analizadores leen los datos cada vez que cambian y, por lo general, se utilizan para establecer el estado válido $ de la entrada. Los documentos tienen ejemplos de ambos.
km6zla

Respuestas:

155

Este tema se cubrió muy bien en una pregunta relacionada: ¿Cómo hacer un filtrado bidireccional en AngularJS?

Para resumir:

  • Los formateadores cambian cómo aparecerán los valores del modelo en la vista.
  • Los analizadores cambian cómo se guardarán los valores de vista en el modelo.

Aquí hay un ejemplo simple, basado en un ejemplo en la documentación de la api de 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();
  });

Puede verlo en acción: 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" />

Cuando escribe un nombre en (vista a modelo), verá que el modelo siempre está en minúsculas. Pero, cuando hace clic en un botón y cambia programáticamente el nombre (modelo para ver), el campo de entrada siempre está en mayúsculas.

j.wittwer
fuente
2
¿Hay alguna forma de establecer este cambio cuando el usuario escribe? Dices "programáticamente", pero estoy tratando de que se formatee el $ viewValue cuando el usuario ingresa en la entrada, por ejemplo, para formatear el número de la tarjeta de crédito
iamyojimbo
3
@SavvasNicholas Si no me equivoco, usaría ngModel.$setViewValue(transformedInput);para configurarlo y ngModel.$render();renderizarlo desde la función $ parsers.
Jacob Ensor
En mi caso, lo que $formattershago, es inmediatamente revertido por $validators. ; (
Mikhail Batcer
1
Para su información, el plunkr al que se hace referencia ya no existe
Chris Brown
1
Noto que el formateador solo funciona si presiona el botón, no si escribe el nombre en el campo
nuander
6

Otro uso para los formateadores y analizadores es cuando desea almacenar fechas en hora UTC y mostrarlas en hora local en las entradas, creé la directiva datepicker y el filtro utcToLocal a continuación para esto.

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

Utiliza este filtro utcToLocal que garantiza que la fecha de entrada esté en el formato correcto antes de convertir a la hora local.

(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 se usa para convertir fechas locales a utc.

pickadate.js es el complemento datepicker utilizado

Jason
fuente