2013-05-05 15 views
13

Zobacz ten jsfiddle: http://jsfiddle.net/8bENp/66/

Jeśli spojrzeć na konsoli JavaScript, zobaczysz coś takiego:

TypeError: Object NaN has no method 'replace' 
    at makeHtml (https://raw.github.com/coreyti/showdown/master/compressed/showdown.js:62:705) 
    at render (http://fiddle.jshell.net/_display/:50:42) 
    at link (http://fiddle.jshell.net/_display/:54:13) 
    at k (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js:42:321) 
    at e (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js:38:198) 
    at k (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js:42:261) 
    at e (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js:38:198) 
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js:37:332 
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js:15:440 
    at Object.e.$eval (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js:85:416) <markdown ng-model="someCode" class="ng-pristine ng-valid"> angular.min.js:60 

Problem polega na tym, że model.$modelValue jest NaN kiedy jego typ nie powinien być nawet liczbą. Niemniej jednak renderowanie oznacza. Mogę dodać test typeof model.$modelValue == 'string', ale wolę leczyć leżącą u jego podstaw przyczynę. Dowolny pomysł?

Odpowiedz

9

Problem w Twojej dyrektywie polega na tym, że kątowy wyzwala zegarek raz przed oceną wyrażenia. Tak więc po raz pierwszy wartość wynosi undefined. Nie wierzę, że można temu zapobiec, ale jak działa AngularJS.

Dodałem parametr val do funkcji renderowania, aby pokazać rzeczywistą obserwowaną wartość (zalogowałem się do konsoli - zobacz skrzypce u dołu). ngModelControllerinitializes $modelValue to NaN, dlatego NaN jest przekazywana do funkcji zamiast undefined.

Ale ponieważ wygląda na to, że funkcja makeHtml oczekuje ciągu znaków, łatwą poprawką jest przekazanie pustego ciągu, jeśli wartość jest falsy (może być jeszcze lepiej przekonwertować go na ciąg znaków).

var htmlText = converter.makeHtml(model.$modelValue || ''); 

Updated fiddle.

+0

Dzięki Martin. Dobrze o tym wiedzieć. –

+0

Dziękuję bardzo. I muszę powiedzieć, że jest to bardzo sprzeczne z intuicją zachowanie, spędziłem godzinę w konsoli, gdzie widziałem wartość, ale mój kod - nie. –

4

Kolejny wariant (tylko, jeśli ktoś znajdzie to pytanie): po prostu zapisz wykonanie dyrektywy w funkcji $ timeout. Na przykład moja dyrektywa, która go używa:

.directive('classOnValue', function($timeout) { 
       return { 
        restrict: 'A', 
        require: 'ngModel', 
        link: function(scope, element, attrs, ngModel) { 
         $timeout(function() { 
          var value = (attrs.value || ngModel.$modelValue || ngModel.$viewValue); 
          if (value) { 
           element.addClass(attrs.classOnValue); 
          } 
         }); 
        }} 
      }) 
+1

Naprawiłem ten problem :) –

+12

To jest takie brudne. – CQQL

+0

Ponieważ ngModel jest fakultatywny, mogą wystąpić błędy, chyba że zostanie sprawdzone, takie jak: 'if (! NgModel) {return;}'. –

24

Nie wiedziałem, że $ modelValue został zainicjowany na NaN i wpadł na podobny problem. Jeśli $ modelValue jest naprawdę potrzebne przy inicjalizacji, rozwiązaniem może być, aby go oglądać, dopóki nie został przypisany nową wartość:

.directive('contentEditor', function(){ 
    return { 
     restrict: 'A', 
     require: 'ngModel', 
     link: function($scope, $element, $attrs, ngModel){ 

      var unregister = $scope.$watch(function(){ 
       return ngModel.$modelValue; 
      }, initialize); 

      function initialize(value){ 
       ngModel.$setViewValue(value); 
       unregister(); 
      } 

      //... 
     } 
    }; 
}); 

$ Zegarek zwraca funkcję wyrejestrowania, więc to może być niezarejestrowany jak tylko nowa wartość została przypisana do $ modelValue.

+0

Nie rozumiem, jak to działa, ale zadziałało.:) –

+0

Bardzo pomocna i poprawna praca z ngModelController – BILL

+0

Gdy wartość powrotu pierwszej funkcji zmieni się, uruchomi się druga funkcja. 'NaN' nigdy nie jest równe' NaN' (dlaczego jest domyślne), więc 'initialize' zawsze działa po pierwszej zmianie modelu. –

13

Myślę, że możesz go również zawinąć w funkcję ngModel.$render.

tak:

.directive('classOnValue', function($timeout) { 
      return { 
       restrict: 'A', 
       require: 'ngModel', 
       link: function(scope, element, attrs, ngModel) { 

        ngModel.$render = function(){ 
         //Do something with your model 
         var actualValue = ngModel.$modelValue; 
        } 

       }} 
     }) 
+0

Głosowanie w górę tej odpowiedzi. Dla tych, którzy chcą wejść w interakcję z modelem, możesz mieć rzeczywistą wartość modelu bez błędów. –

+0

Naprawiono również mój problem !! –

Powiązane problemy