Was ist der Unterschied zwischen ngModel. $ ModelValue und ngModel. $ ViewValue

94

Ich habe die folgende ckEditor-Direktive. Unten sind zwei Variationen aufgeführt, die ich anhand von Beispielen zum Festlegen der Daten im Editor gesehen habe:

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

Kann mir jemand sagen, was der Unterschied ist zwischen:

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

Und welches soll ich benutzen. Ich habe mir die eckige Dokumentation angesehen und dort steht:

$viewValue

Actual string value in the view.

$modelValue

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

Ich habe keine Ahnung, was der Autor meinte, als er dies in das Dokument schrieb :-(

Samantha JT Star
quelle

Antworten:

151

Sie sehen sich die richtige Dokumentation an, aber es kann sein, dass Sie ein wenig verwirrt sind. Die $modelValueund $viewValuehaben einen deutlichen Unterschied. Es ist das:

Wie Sie bereits oben erwähnt haben:

$viewValue:Tatsächlicher Zeichenfolgenwert (oder Objektwert) in der Ansicht.
$modelValue:Der Wert im Modell, an den das Steuerelement gebunden ist.

Ich gehe davon aus, dass sich Ihr ngModel auf ein <input />Element bezieht ...? Sie <input>haben also einen Zeichenfolgenwert, der dem Benutzer angezeigt wird, oder? Das eigentliche Modell könnte jedoch eine andere Version dieser Zeichenfolge sein. Beispielsweise zeigt die Eingabe möglicherweise die Zeichenfolge an, '200'aber die <input type="number">(zum Beispiel) enthält tatsächlich einen Modellwert 200als Ganzzahl. Die Zeichenfolgendarstellung, die Sie in der "Ansicht" anzeigen, <input>ist also die ngModel.$viewValueund die numerische Darstellung ist die ngModel.$modelValue.

Ein anderes Beispiel wäre ein Ort, <input type="date">an dem $viewValuedas so etwas wie wäre, Jan 01, 2000und das $modelValuewäre ein tatsächliches Javascript- DateObjekt, das diese Datumszeichenfolge darstellt. Ist das sinnvoll?

Ich hoffe das beantwortet deine Frage.

Tennisagent
quelle
Also ist im Grunde $viewValueimmer eine Zeichenfolge?
CDMckay
7
Wie die Dokumente sagen : $viewValue: Actual string value in the view.. Also ja.
Tennisgent
7
Noch ein Hinweis. Wenn ein <input type="text">Wert leer ist, das $modelValueist Eigentum undefined, während das $viewValueist ''leerer String. Dies kann einen Unterschied machen, wenn Sie an der "Länge" der schnüffeln, die $modelValuenicht funktioniert, aber funktioniert $viewValue.
BradGreens
8
Das $viewValueist nicht immer eine Zeichenfolge. Es ist eine Zeichenfolge für die aktuellen Angular-Kernanweisungen, kann jedoch ein Grundelement oder ein Objekt in Ihren benutzerdefinierten Steuerelementen sein. Ein gutes Beispiel ist die <input file="type">Komponente, in der viewValue ein FileListObjekt mit vom Benutzer angehängten Dateien enthält . Die Angular-Dokumente sind derzeit verwirrend und sollten aktualisiert werden.
Demisx
4
Auch nicht, wenn die Eingabe ungültig ist, wird der $ modelValue nicht gesetzt. Das heißt, wenn Sie <input ng-minlength = "8" ...> haben und Ihre Eingabe nur 5 Zeichen lang ist, zeigt der $ viewValue diese 5 Zeichen an, aber $ modelValue existiert nicht.
Honkskillet
27

Sie können solche Dinge sehen:

  • $modelValue ist Ihre externe API, dh etwas, das Ihrem Controller ausgesetzt ist.
  • $viewValue Ist Ihre interne API, sollten Sie sie nur intern verwenden.

Beim Bearbeiten $viewValuewird die Rendermethode nicht aufgerufen, da es sich um das "gerenderte Modell" handelt. Sie müssen dies manuell tun, während die Rendermethode bei $modelValueÄnderungen automatisch aufgerufen wird .

Die Informationen bleiben jedoch dank $formattersund erhalten $parsers:

  • Wenn Sie sich ändern $viewValue, $parserswird es zurück in übersetzt $modelValue.
  • Wenn Sie ändern $modelValue, $formatterswird es in konvertieren $viewValue.
Vianney Dupoy de Guitard
quelle
Beim Bearbeiten von $ viewValue wird die Rendermethode nicht aufgerufen. Wenn Sie $ viewValue ändern, übersetzt $ parsers sie zurück in $ modelValue.means $ modelvalue change.und die Rendermethode wird automatisch bei $ modelValue-Modifikationen aufgerufen. Wenn sich $ viewValue ändert, wird die Rendermethode aufgerufen. ist es ?
Mukund Kumar
1
Sie müssen sich in die Zwei-Wege-Bindungspipeline Angular ngModel vertiefen, um zu verstehen, wie dies funktioniert. Bei der Aktualisierung $viewValueüber eine setViewValue(viewValue)Methode treten Parser / Validatoren (falls vorhanden) ein und analysieren diese viewValuein den modelValue, validieren sie, schreiben sie in den Bereich und treten dann aus viewChangeListeners. Bei der nächsten Ausführung des Digests wird der Modellwert aus dem Bereich abgerufen und mit dem $ modelValue im Controller verglichen: github.com/angular/angular.js/blob/master/src/ng/directive/… . Wenn sie gleich sind (und in Ihrem Szenario gleich sind), wird sie zurückgegeben.
Demisx
18

Angular muss zwei Ansichten von ngModel-Daten verfolgen - es gibt die Daten, die vom DOM (Browser) gesehen werden, und dann gibt es Angulars verarbeitete Darstellung dieser Werte. Das $viewValueist der DOM Seiten Wert. So hat beispielsweise der Benutzer in einem <input>das $viewValueeingegeben, was der Benutzer in seinen Browser eingegeben hat.

Sobald jemand etwas <input>eingibt, $viewValuewird es von $ parsers verarbeitet und in Angulars Ansicht des aufgerufenen Werts umgewandelt $modelValue.

Sie können sich also vorstellen, $modelValuedass Angulars verarbeitete Version des Werts der Wert ist, den Sie im Modell sehen, während $viewValuees sich um die Rohversion handelt.

Um diesen Schritt weiter zu gehen, stellen Sie sich vor, wir tun etwas, das das verändert $modelValue. Angular erkennt diese Änderung und ruft $ formatters auf, um ein aktualisiertes $viewValue(basierend auf dem neuen $ modelValue) zu erstellen, das an das DOM gesendet werden soll.

KayakDave
quelle
Du meinst $ modelValue oder $ modelView? Wenn $ modelValue, korrigieren Sie bitte den Tippfehler.
Plankton