model.$modelValue is NaN in directive

匿名 (未验证) 提交于 2019-12-03 02:06:01

问题:

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)  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?

回答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.



回答2:

I was not aware that $modelValue was initialized to NaN and ran into a similar issue. If the $modelValue is really needed at initialization, a solution may be to watch it until it has been assigned a new value:

.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();             }              //...         }     }; }); 

The $watch returns a deregistration function, so it can be unregistered as soon as a new value has been assigned to $modelValue.



回答3:

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


回答4:

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


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!