Formatadores e analisadores ngModel

103

Postei a mesma pergunta de forma diferente, mas ninguém respondeu. Não estou obtendo uma imagem clara do que os Formatadores e Analisadores fazem no angular js.

Pela definição, os Formatadores e os Analisadores são semelhantes a mim. Talvez eu esteja errado, pois sou novo neste angularjs.

Definição de formatadores

Matriz de funções a serem executadas, como um pipeline, sempre que o valor do modelo muda. Cada função é chamada, por sua vez, passando o valor para a próxima. Usado para formatar / converter valores para exibição no controle e validação.

Definição de Parsers

Matriz de funções a serem executadas, como um pipeline, sempre que o controle lê o valor do DOM. Cada função é chamada, por sua vez, passando o valor para a próxima. Usado para higienizar / converter o valor, bem como validação. Para validação, os analisadores devem atualizar o estado de validade usando $ setValidity () e retornar indefinido para valores inválidos.

Por favor, me ajude a entender os dois recursos com um exemplo simples. Uma ilustração simples de ambos será apreciada.

RONE
fonte
2
Os formatadores modificam o valor exibido de um modelo, como a exibição (123) 123-1234de um número de telefone. Os analisadores leem os dados sempre que eles mudam e normalmente são usados ​​para definir o estado $ valid da entrada. Os documentos têm exemplos de ambos.
km6zla

Respostas:

155

Este tópico foi muito bem abordado em uma questão relacionada: Como fazer a filtragem bidirecional no AngularJS?

Para resumir:

  • Os formatadores mudam como os valores do modelo aparecerão na visualização.
  • Os analisadores alteram como os valores da visualização serão salvos no modelo.

Aqui está um exemplo simples, baseado em um exemplo na documentação da 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();
  });

Você pode vê-lo em ação: 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" />

Ao digitar um nome em (ver para o modelo), você verá que o modelo está sempre em minúsculas. Mas, quando você clica em um botão e altera o nome de maneira programática (modelo para visualização), o campo de entrada está sempre em maiúsculas.

j.wittwer
fonte
2
existe alguma maneira de definir essa mudança conforme o usuário digita? Você diz "programaticamente", mas estou tentando fazer com que $ viewValue seja formatado conforme o usuário insere na entrada, por exemplo, para formatação de número de cartão de crédito
iamyojimbo
3
@SavvasNicholas Se não me engano, você usaria ngModel.$setViewValue(transformedInput);para configurá-lo e ngModel.$render();renderizá-lo a partir da função $ parsers.
Jacob Ensor
No meu caso, o que $formattersfazer, é imediatamente revertido por $validators. ; (
Mikhail Batcer
1
Para sua informação, o plunkr referenciado não existe mais
Chris Brown
1
Percebi que o formatador só funciona se você apertar o botão, não se digitar o nome no campo
nuander
6

Outro uso para formatadores e analisadores é quando você deseja armazenar datas no horário UTC e exibi-los no horário local nas entradas. Criei a diretiva datepicker abaixo e o filtro utcToLocal para isso.

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

Ele usa esse filtro utcToLocal que garante que a data de entrada esteja no formato correto antes de converter para a 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 é usado para converter datas locais em datas utc.

pickadate.js é o plugin datepicker usado

Jason
fonte