Qual é a diferença entre ngModel. $ ModelValue e ngModel. $ ViewValue

94

Eu tenho a seguinte diretiva ckEditor. Na parte inferior, estão duas variações que vi nos exemplos de como definir os dados no editor:

app.directive('ckEditor', [function () {
    return {
        require: '?ngModel',
        link: function ($scope, elm, attr, ngModel) {

            var ck = null;
            var config = attr.editorSize;
            if (config == 'wide') {
                ck = CKEDITOR.replace(elm[0], { customConfig: 'config-wide.js' });
            } else {
                ck = CKEDITOR.replace(elm[0], { customConfig: 'config-narrow.js' });
            }


            function updateModel() {
                $scope.$apply(function () {
                    ngModel.$setViewValue(ck.getData());
                });
            }

            $scope.$on('modalObjectSet', function (e, modalData) {
                // force a call to render
                ngModel.$render();
            });

            ck.on('change', updateModel);
            ck.on('mode', updateModel);
            ck.on('key', updateModel);
            ck.on('dataReady', updateModel);

            ck.on('instanceReady', function () {
                ngModel.$render();
            });

            ck.on('insertElement', function () {
                setTimeout(function () {
                    $scope.$apply(function () {
                        ngModel.$setViewValue(ck.getData());
                    });
                }, 1000);
            });

            ngModel.$render = function (value) {
                ck.setData(ngModel.$modelValue);
            };

            ngModel.$render = function (value) {
                ck.setData(ngModel.$viewValue);
            };
        }
    };
}])

Alguém pode me dizer qual é a diferença entre:

ck.setData(ngModel.$modelValue);
ck.setData(ngModel.$viewValue);

E qual devo usar. Eu olhei a documentação angular e dizia:

$viewValue

Actual string value in the view.

$modelValue

The value in the model, that the control is bound to.

Não tenho ideia do que o autor quis dizer quando escreveu isso no documento :-(

Samantha JT Star
fonte

Respostas:

151

Você está vendo a documentação correta, mas pode ser que esteja um pouco confuso. Os $modelValuee $viewValuetêm uma diferença distinta. É isto:

Como você já observou acima:

$viewValue:Valor real da string (ou objeto) na visualização.
$modelValue:O valor no modelo ao qual o controle está vinculado.

Vou supor que seu ngModel está se referindo a um <input />elemento ...? Portanto, seu <input>tem um valor de string que exibe ao usuário, certo? Mas o modelo real pode ser alguma outra versão dessa string. Por exemplo, a entrada pode mostrar a string, '200'mas <input type="number">(por exemplo) conterá na verdade um valor de modelo de 200como um inteiro. Portanto, a representação de string que você "vê" no <input>é o ngModel.$viewValuee a representação numérica será o ngModel.$modelValue.

Outro exemplo seria um <input type="date">em $viewValueque seria algo como Jan 01, 2000e $modelValueseria um Dateobjeto javascript real que representa aquela string de data. Isso faz sentido?

Espero que isso responda a sua pergunta.

tenista
fonte
Então, basicamente, $viewValueé sempre uma string?
cdmckay
7
Como os médicos dizem: $viewValue: Actual string value in the view.. Então sim.
tenista de
7
Outra nota. Quando um <input type="text">valor está vazio, a $modelValuepropriedade é undefined, enquanto o $viewValueé uma ''string vazia. Isso pode fazer diferença se você estiver farejando o "comprimento" do $modelValueque não funcionará, mas $viewValuefuncionará.
BradGreens,
8
O $viewValuenem sempre é uma string. É uma string para as diretivas principais Angular atuais, mas pode ser uma primitiva ou um objeto em seus controles personalizados. Um bom exemplo é o <input file="type">componente, onde viewValue contém o FileListobjeto com arquivos anexados pelo usuário. Os documentos do Angular são confusos sobre isso agora e devem ser atualizados.
demisx
4
Além disso, se a entrada for inválida, o $ modelValue não será definido. Ou seja, se você tiver <input ng-minlength = "8" ...> e a entrada tiver apenas 5 caracteres, o $ viewValue mostrará esses 5 caracteres, mas $ modelValue não existirá.
honkskillet
27

Você pode ver coisas assim:

  • $modelValue é a sua API externa, ou seja, algo exposto ao seu controlador.
  • $viewValue é sua API interna, você deve usá-la apenas internamente.

Ao editar $viewValue, o método de renderização não será chamado, pois é o "modelo renderizado". Você terá que fazer isso manualmente, enquanto o método de renderização será chamado automaticamente após as $modelValuemodificações.

No entanto, as informações permanecerão consistentes, graças a $formatterse $parsers:

  • Se você mudar $viewValue, $parserso traduzirá de volta para $modelValue.
  • Se você alterar $modelValue, $formatterso converterá em $viewValue.
Vianney Dupoy de Guitard
fonte
Ao editar $ viewValue, o método de renderização não será chamado. Se você alterar $ viewValue, $ parsers o traduzirá de volta para $ modelValue.means $ modelvalue change.and o método de renderização será chamado automaticamente nas modificações de $ modelValue.so indiretamente, quando $ viewValue muda, o método render é chamado. é isso ?
Mukund Kumar
1
Você precisa se aprofundar no pipeline de vinculação bidirecional do Angular ngModel para entender como isso funciona. Ao atualizar $viewValuepor meio do setViewValue(viewValue)método, os analisadores / validadores viewValueiniciam (se houver) e analisam isso no modelValue, validam, gravam no escopo e depois executam o kick viewChangeListeners. Na próxima vez que o resumo for executado, o valor do modelo será recuperado do escopo e comparado ao $ modelValue no controlador: github.com/angular/angular.js/blob/master/src/ng/directive/… . Se eles forem iguais (e serão iguais no seu cenário), ele retorna.
demisx
18

O Angular precisa manter o controle de duas visualizações dos dados do ngModel - há os dados conforme vistos pelo DOM (navegador) e, em seguida, há a representação processada do Angular desses valores. O $viewValueé o valor do lado DOM. Assim, por exemplo, em uma <input>o $viewValueé o que o usuário digitou no seu browser.

Uma vez que alguém digita algo <input>, $viewValueé processado por $ parsers e transformado na visão do Angular do valor que é chamado $modelValue.

Portanto, você pode pensar em $modelValueser a versão processada do valor do angular, o valor que você vê no modelo, enquanto $viewValueé a versão bruta.

Para dar um passo adiante, imagine que fazemos algo que muda o $modelValue. Angular vê essa mudança e chama $ formatters para criar um valor atualizado $viewValue(baseado no novo $ modelValue) a ser enviado ao DOM.

KayakDave
fonte
u significa $ modelValue ou $ modelView ?? Se $ modelValue, corrija o erro de digitação.
Plâncton de