model.$modelValue is NaN in directive

14,773

Solution 1

The problem in your directive is that angular triggers the watch once before the expression has been evaluated. So the very first time the value is undefined. I don't believe that can be prevented, but is how AngularJS works.

I added a val parameter to your render function to show the actual watched value (logged to the console--see the fiddle at the bottom). The ngModelController initializes $modelValue to NaN, that's why NaN is passed to the function instead of undefined.

But since it seems as if the makeHtml function expects a string, an easy fix is to pass it an empty string if the value is falsy (might be even better to convert it to a string).

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

Updated fiddle.

Solution 2

I think you can also wrap it in a ngModel.$render function.

Like so:

.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;
                   }

               }}
       })

Solution 3

Another variant (just if somebody will find that question here): just wrap execution of directive in $timeout function. As example, my directive which use it:

.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);
                           }
                       });
                   }}
           })
Share:
14,773
Steve
Author by

Steve

Updated on June 06, 2022

Comments

  • Steve
    Steve about 2 years

    See this jsfiddle: http://jsfiddle.net/8bENp/66/

    If you look at the JavaScript console, you'll see something like this:

    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
    

    The problem is that model.$modelValue is NaN when its type shouldn't even be a number. Nevertheless, the markdown renders. I could add a typeof model.$modelValue == 'string' check, but I'd rather treat the underlying cause. Any idea?

  • Steve
    Steve about 11 years
    Thanks Martin. Good to know this.
  • OZ_
    OZ_ almost 11 years
    Thank you very much. And have to say that it's very counter-intuitive behavior, I spent a hour in console where I saw value but my code - not.
  • Kevin Beal
    Kevin Beal over 10 years
    This fixed my issue :)
  • Admin
    Admin almost 10 years
    Since ngModel is made facultative, errors may occur unless a check is made, such as : if (!ngModel) {return;}.
  • OZ_
    OZ_ over 9 years
    @timmy because timeout will be called in digest cycle of Angular.
  • timmy
    timmy over 9 years
    Where in the digest cycle will the code be executed? I couldn't find any docs on this. How did someone even know how to perform this technique? Seems like magic if one doesn't understand the cycle and how to tap into it :)
  • Vladius
    Vladius almost 9 years
    It's a good solution, better then using watches. Using timeouts is actually an ok, and angular-style.
  • Rogers Sampaio
    Rogers Sampaio over 8 years
    Voting up this answer. For those want to interact with the model you can have the actual model value without errors.
  • Mudaser Ali
    Mudaser Ali almost 8 years
    it fixed my issue as well!!