¿Cuál es la diferencia entre ngModel. $ ModelValue y ngModel. $ ViewValue?

94

Tengo la siguiente directiva ckEditor. En la parte inferior hay dos variaciones que he visto en ejemplos sobre cómo configurar los datos en el 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);
            };
        }
    };
}])

¿Alguien puede decirme cuál es la diferencia entre:

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

Y cuál debería usar. Miré la documentación angular y dice:

$viewValue

Actual string value in the view.

$modelValue

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

No tengo idea de lo que quiso decir el autor cuando escribió esto en el documento :-(

Samantha JT Star
fuente

Respuestas:

151

Está viendo la documentación correcta, pero es posible que esté un poco confundido. El $modelValuey $viewValuetienen una diferencia clara. Es esto:

Como ya señaló anteriormente:

$viewValue:Valor de cadena (u objeto) real en la vista.
$modelValue:El valor en el modelo al que está vinculado el control.

¿Voy a suponer que su ngModel se refiere a un <input />elemento ...? Entonces tu <input>tiene un valor de cadena que se muestra al usuario, ¿verdad? Pero el modelo real podría ser alguna otra versión de esa cadena. Por ejemplo, la entrada puede mostrar la cadena '200'pero <input type="number">(por ejemplo) en realidad contendrá un valor de modelo 200como un número entero. Así que la representación de cadena que "ve" en el <input>es el ngModel.$viewValuey la representación numérica será el ngModel.$modelValue.

Otro ejemplo sería <input type="date">donde el $viewValuesería algo como Jan 01, 2000y $modelValuesería un Dateobjeto javascript real que representa esa cadena de fecha. ¿Tiene sentido?

Espero haber respondido a tu pregunta.

tenista
fuente
Entonces, básicamente, ¿ $viewValuees siempre una cuerda?
cdmckay
7
Como dicen los documentos: $viewValue: Actual string value in the view.. Entonces sí.
tennisgent
7
Otra nota. Cuando un <input type="text">valor está vacío, la $modelValuepropiedad es undefined, mientras que $viewValuees una ''cadena vacía. Esto puede marcar la diferencia si está olfateando la "longitud" del $modelValueque no funcionará, pero $viewValuesí.
BradGreens
8
El $viewValueno siempre es una cadena. Es una cadena para las directivas centrales actuales de Angular, pero puede ser una primitiva o un Objeto en sus controles personalizados. Un buen ejemplo es el <input file="type">componente, donde viewValue contiene un FileListobjeto con archivos adjuntos por el usuario. Los documentos de Angular son confusos sobre esto en este momento y deberían actualizarse.
demisx
4
Tampoco si la entrada no es válida, $ modelValue no se establecerá. Es decir, si tiene <input ng-minlength = "8" ...> y su entrada tiene solo 5 caracteres, $ viewValue mostrará esos 5 caracteres pero $ modelValue no existirá.
honkskillet
27

Puedes ver cosas como esta:

  • $modelValue es su API externa, es decir, algo expuesto a su controlador.
  • $viewValue es su API interna, debe usarla solo internamente.

Al editar $viewValue, no se llamará al método de renderizado, porque es el "modelo renderizado". Tendrá que hacerlo manualmente, mientras que el método de renderizado se llamará automáticamente al realizar $modelValuemodificaciones.

Sin embargo, la información seguirá siendo consistente, gracias a $formattersy $parsers:

  • Si cambia $viewValue, $parserslo traducirá de nuevo a $modelValue.
  • Si cambia $modelValue, $formatterslo convertirá a $viewValue.
Vianney Dupoy de Guitard
fuente
Al editar $ viewValue, no se llamará al método de renderizado.Si cambia $ viewValue, $ parsers lo traducirán de nuevo a $ modelValue.means $ modelvalue change. Y el método de renderizado se llamará automáticamente tras las modificaciones de $ modelValue. cuando cambia $ viewValue, se llama al método render. Lo es ?
Mukund Kumar
1
Debe profundizar en la tubería de enlace bidireccional ngModel de Angular para comprender cómo funciona esto. Cuando se actualiza a $viewValuetravés del setViewValue(viewValue)método, los analizadores / validadores se viewValueactivan (si los hay) y lo analizan en modelValue, lo validan, lo escriben en el alcance y luego lo apagan viewChangeListeners. La próxima vez que se ejecute el resumen, el valor del modelo se recupera del alcance y se compara con $ modelValue en el controlador: github.com/angular/angular.js/blob/master/src/ng/directive/… . Si son iguales (y serán iguales en su escenario), regresa.
demisx
18

Angular tiene que realizar un seguimiento de dos vistas de los datos de ngModel: están los datos como los ve el DOM (navegador) y luego está la representación procesada de Angular de esos valores. El $viewValuees el valor lado DOM. Así, por ejemplo, en un <input>el $viewValuees lo que el usuario escribió en su navegador.

Una vez que alguien escribe algo en <input>continuación, $viewValuese procesa por $ analizadores y convertido en vista de angular del valor que se llama $modelValue.

Entonces, puede pensar en $modelValueser la versión procesada de angular del valor, el valor que ve en el modelo, mientras que $viewValuees la versión sin procesar.

Para dar un paso más, imagine que hacemos algo que cambia la $modelValue . Angular ve este cambio y llama a $ formateadores para crear una actualización $viewValue(basada en el nuevo $ modelValue) que se enviará al DOM.

KayakDave
fuente
¿Quieres decir $ modelValue o $ modelView? Si es $ modelValue, corrija el error tipográfico.
Plancton