Qual è la differenza tra ngModel. $ ModelValue e ngModel. $ ViewValue


94

Ho la seguente direttiva ckEditor. In basso ci sono due varianti che ho visto da esempi su come impostare i dati nell'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);
            };
        }
    };
}])

Qualcuno può dirmi qual è la differenza tra:

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

E quale dovrei usare. Ho guardato la documentazione angolare e dice:

$viewValue

Actual string value in the view.

$modelValue

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

Non ho idea di cosa intendesse l'autore quando ha scritto questo nel documento :-(

Risposte:


151

Stai guardando la documentazione corretta, ma potrebbe essere solo che sei un po 'confuso. L' $modelValuee $viewValuehanno una chiara differenza. È questo:

Come hai già notato sopra:

$viewValue:Valore effettivo della stringa (o dell'oggetto) nella vista.
$modelValue:Il valore nel modello a cui è associato il controllo.

Presumo che il tuo ngModel si riferisca a un <input />elemento ...? Quindi il tuo <input>ha un valore stringa che mostra all'utente, giusto? Ma il modello effettivo potrebbe essere un'altra versione di quella stringa. Ad esempio, l'input potrebbe mostrare la stringa '200'ma <input type="number">(per esempio) in realtà conterrà un valore di modello 200come numero intero. Quindi la rappresentazione di stringa che "vedi" in <input>è il ngModel.$viewValuee la rappresentazione numerica sarà il ngModel.$modelValue.

Un altro esempio potrebbe essere un <input type="date">dove $viewValuesarebbe qualcosa di simile Jan 01, 2000e $modelValuesarebbe un vero Dateoggetto javascript che rappresenta quella stringa di data. Ha senso?

Spero che risponda alla tua domanda.


Quindi in fondo, $viewValueè sempre una stringa?
cdmckay

7
Come i documenti dicono: $viewValue: Actual string value in the view.. Quindi sì.
tennisgent

7
Un'altra nota. Quando un <input type="text">valore è vuoto, la $modelValueproprietà è undefined, mentre la $viewValueè ''una stringa vuota. Questo può fare la differenza se stai annusando la "lunghezza" del $modelValuequale non funzionerà, ma lo $viewValuefarà.
BradGreens

8
Non $viewValueè sempre una stringa. È una stringa per le attuali direttive principali di Angular, ma può essere una primitiva o un Object nei controlli personalizzati. Un buon esempio è il <input file="type">componente, dove viewValue contiene FileListoggetti con file allegati dall'utente. I documenti Angular sono confusi su questo in questo momento e dovrebbero essere aggiornati.
demisx

4
Inoltre, se l'input non è valido, $ modelValue non verrà impostato. Cioè, se hai <input ng-minlength = "8" ...> e inserisci solo 5 caratteri, $ viewValue mostrerà quei 5 caratteri ma $ modelValue non esisterà.
honkskillet

27

Puoi vedere cose come questa:

  • $modelValue è la tua API esterna, vale a dire, qualcosa esposto al tuo controller.
  • $viewValue è la tua API interna, dovresti usarla solo internamente.

Durante la modifica $viewValue, il metodo render non sarà chiamato, perché è il "modello renderizzato". Dovrai farlo manualmente, mentre il metodo di rendering verrà chiamato automaticamente in caso di $modelValuemodifiche.

Tuttavia, le informazioni rimarranno coerenti, grazie a $formatterse $parsers:

  • Se lo modifichi $viewValue, $parserslo tradurrà di nuovo in $modelValue.
  • Se lo modifichi $modelValue, $formatterslo convertirà in $viewValue.

Quando si modifica $ viewValue, il metodo di rendering non verrà chiamato. Se si modifica $ viewValue, $ parser lo tradurrà di nuovo in $ modelValue.means $ modelvalue change. E il metodo di rendering verrà chiamato automaticamente su $ modelValue modifiche. Così indirettamente, quando $ viewValue cambia, viene chiamato il metodo render. è ?
Mukund Kumar

1
È necessario approfondire la pipeline di binding bidirezionale di Angular ngModel per capire come funziona. Quando si aggiorna $viewValuetramite il setViewValue(viewValue)metodo, i parser / validatori si viewValueattivano (se presenti) e lo analizzano in modelValue, lo convalidano, lo scrivono nello scope e poi lo kick of viewChangeListeners. La prossima volta che viene eseguito il digest, il valore del modello viene recuperato dall'ambito e confrontato con $ modelValue nel controller: github.com/angular/angular.js/blob/master/src/ng/directive/… . Se sono uguali (e saranno uguali nel tuo scenario), allora ritorna.
demisx

18

Angular deve tenere traccia di due visualizzazioni dei dati di ngModel: ci sono i dati visti dal DOM (browser) e poi c'è la rappresentazione elaborata di Angular di quei valori. Il $viewValueè il valore lato DOM. Così, per esempio, in un <input>l' $viewValueè ciò che l'utente ha digitato al proprio browser.

Una volta che qualcuno scrive qualcosa in <input>poi $viewValueviene processato da $ parser e trasformati in vista di angolare del valore che si chiama $modelValue.

Quindi puoi pensare di $modelValueessere la versione elaborata di angular del valore, il valore che vedi nel modello, mentre $viewValueè la versione grezza.

Per fare un ulteriore passo avanti, immagina di fare qualcosa che cambi il file $modelValue. Angular vede questa modifica e chiama $ formatters per creare un aggiornamento $viewValue(basato sul nuovo $ modelValue) da inviare al DOM.


intendi $ modelValue o $ modelView ?? Se $ modelValue, correggi gentilmente l'errore di battitura.
Plancton
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.