Jaka jest różnica między ngModel. $ ModelValue a ngModel. $ ViewValue

94

Mam następującą dyrektywę ckEditor. U dołu znajdują się dwie odmiany, które widziałem na przykładach, jak ustawić dane w edytorze:

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

Czy ktoś może mi powiedzieć, jaka jest różnica między:

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

I którego powinienem użyć. Spojrzałem na dokumentację kątową i mówi:

$viewValue

Actual string value in the view.

$modelValue

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

Nie mam pojęcia, co autor miał na myśli, pisząc to w dokumencie :-(

Samantha JT Star
źródło

Odpowiedzi:

151

Patrzysz na właściwą dokumentację, ale może być tak, że jesteś trochę zdezorientowany. $modelValueI $viewValuejeden wyraźną różnicę. To jest to:

Jak już zauważyłeś powyżej:

$viewValue:Rzeczywista wartość ciągu (lub obiektu) w widoku.
$modelValue:Wartość w modelu, z którą jest powiązany formant.

Zakładam, że twój ngModel odnosi się do <input />elementu ...? Więc masz <input>wartość ciągu, którą wyświetla użytkownikowi, prawda? Ale rzeczywisty model może być inną wersją tego ciągu. Na przykład dane wejściowe mogą pokazywać ciąg, '200'ale <input type="number">(na przykład) faktycznie będzie zawierać wartość modelu 200jako liczbę całkowitą. Zatem reprezentacja ciągu, którą "przeglądasz" w, <input>to, ngModel.$viewValuea reprezentacją numeryczną będzie ngModel.$modelValue.

Innym przykładem może być <input type="date">, gdzie $viewValuebyłoby coś takiego Jan 01, 2000i $modelValuebyłoby rzeczywiste javascript Dateobiekt, który reprezentuje tę datę ciąg. Czy to ma sens?

Mam nadzieję, że to odpowiada na twoje pytanie.

tenisista
źródło
Czy w zasadzie $viewValuezawsze jest ciągiem?
cdmckay
7
Jak docs powiedzieć: $viewValue: Actual string value in the view.. Więc tak.
tenisista
7
Kolejna uwaga. Gdy <input type="text">wartość jest pusta, $modelValuewłaściwość to undefined, a ciąg $viewValuejest ''pusty. Może to mieć znaczenie, jeśli wąchasz „długość” tego, $modelValueco nie zadziała, ale $viewValuezadziała.
BradGreens,
8
$viewValueNie zawsze jest ciągiem. Jest to ciąg dla bieżących dyrektyw rdzenia Angular, ale może to być prymityw lub Object w kontrolkach niestandardowych. Dobrym przykładem jest <input file="type">komponent, w którym viewValue zawiera FileListobiekt z załączonymi przez użytkownika plikami. Dokumentacja Angulara jest teraz niejasna i powinna zostać zaktualizowana.
demisx
4
Również nie, jeśli dane wejściowe są nieprawidłowe, $ modelValue nie zostanie ustawione. To znaczy, jeśli masz <input ng-minlength = "8" ...> i wprowadzisz tylko 5 znaków, $ viewValue pokaże te 5 znaków, ale $ modelValue nie będzie istnieć.
honkskillet
27

Możesz zobaczyć takie rzeczy:

  • $modelValue to twój zewnętrzny interfejs API, to znaczy coś, co jest widoczne dla twojego kontrolera.
  • $viewValue to Twój wewnętrzny interfejs API, powinieneś używać go tylko wewnętrznie.

Podczas edycji $viewValuemetoda renderowania nie zostanie wywołana, ponieważ jest to „renderowany model”. Będziesz musiał to zrobić ręcznie, podczas gdy metoda renderowania zostanie wywołana automatycznie po $modelValuemodyfikacjach.

Jednak informacje pozostaną spójne, dzięki $formattersi $parsers:

  • Jeśli zmienisz $viewValue, $parsersprzetłumaczy to z powrotem na $modelValue.
  • Jeśli zmienisz $modelValue, $formattersprzekonwertuje go na $viewValue.
Vianney Dupoy de Guitard
źródło
Podczas edycji $ viewValue metoda renderowania nie zostanie wywołana.Jeśli zmienisz $ viewValue, $ parsers przetłumaczy to z powrotem na $ modelValue.means $ modelvalue change. A metoda renderowania zostanie wywołana automatycznie po modyfikacjach $ modelValue. Więc pośrednio, kiedy $ viewValue się zmienia, wywoływana jest metoda renderowania. czy to jest
Mukund Kumar
1
Musisz zagłębić się w dwukierunkowy potok wiązania Angular ngModel, aby zrozumieć, jak to działa. Podczas aktualizacji $viewValueza pomocą setViewValue(viewValue)metody, parsery / walidatory viewValueuruchamiają się (jeśli są) i analizują to w modelValue, sprawdzają poprawność, zapisują w zakresie, a następnie wyrzucają viewChangeListeners. Przy następnym uruchomieniu podsumowania wartość modelu jest pobierana z zakresu i porównywana z wartością $ modelValue w kontrolerze: github.com/angular/angular.js/blob/master/src/ng/directive/… . Jeśli są równe (i będą równe w twoim scenariuszu), to powróci.
demisx
18

Angular musi śledzić dwa widoki danych ngModel - są dane widziane przez DOM (przeglądarkę), a następnie jest przetworzona reprezentacja tych wartości przez Angular. Plik$viewValue jest wartość po stronie DOM. Na przykład w <input>polu $viewValuejest to, co użytkownik wpisał w przeglądarce.

Po wpisze coś w <input>następnie $viewValuejest przetwarzany przez $ parserami i przekształcony widzenia kątowego w wartości, które nazywa $modelValue.

Możesz więc pomyśleć o $modelValuebyciu przetworzoną wersją wartości kątowej, wartością, którą widzisz w modelu, podczas gdy $viewValuejest to wersja surowa.

Aby pójść o krok dalej, wyobraź sobie, że robimy coś, co zmienia $modelValue. Angular widzi tę zmianę i wywołuje $ formatters w celu utworzenia zaktualizowanej $viewValue(opartej na nowej wartości $ modelValue), która ma być wysłana do DOM.

KayakDave
źródło
u oznacza $ modelValue lub $ modelView ?? Jeśli $ modelValue, popraw literówkę.
Plankton