model.$modelValue is NaN in directive
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 || '');
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);
}
});
}}
})
Steve
Updated on June 06, 2022Comments
-
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
isNaN
when its type shouldn't even be a number. Nevertheless, the markdown renders. I could add atypeof model.$modelValue == 'string'
check, but I'd rather treat the underlying cause. Any idea? -
Steve about 11 yearsThanks Martin. Good to know this.
-
OZ_ almost 11 yearsThank 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 over 10 yearsThis fixed my issue :)
-
Admin almost 10 yearsSince ngModel is made facultative, errors may occur unless a check is made, such as :
if (!ngModel) {return;}
. -
OZ_ over 9 years@timmy because timeout will be called in digest cycle of Angular.
-
timmy over 9 yearsWhere 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 almost 9 yearsIt's a good solution, better then using watches. Using timeouts is actually an ok, and angular-style.
-
Rogers Sampaio over 8 yearsVoting up this answer. For those want to interact with the model you can have the actual model value without errors.
-
Mudaser Ali almost 8 yearsit fixed my issue as well!!