Модель. $modelValue - NaN в директиве
См. этот jsfiddle: http://jsfiddle.net/8bENp/66/
Если вы посмотрите на консоль JavaScript, вы увидите что-то вроде этого:
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
Проблема заключается в том, что model.$modelValue
есть NaN
, когда его тип не должен быть даже числом. Тем не менее, уценка делает. Я мог бы добавить проверку typeof model.$modelValue == 'string'
, но я бы скорее рассмотрел основную причину. Любая идея?
Ответы
Ответ 1
Проблема в вашей директиве заключается в том, что angular запускает часы один раз до того, как выражение будет оценено. Поэтому в первый раз значение undefined
. Я не верю, что это можно предотвратить, но как работает AngularJS.
Я добавил параметр val
к вашей функции рендеринга, чтобы показать фактическое наблюдаемое значение (зарегистрировалось на консоли - см. скрипку внизу). ngModelController
инициализирует $modelValue
для NaN, поэтому NaN
передается функции вместо undefined
.
Но так как кажется, что функция makeHtml
ожидает строку, простое исправление должно передать ей пустую строку, если значение ложно (может быть даже лучше преобразовать его в строку).
var htmlText = converter.makeHtml(model.$modelValue || '');
Обновлена скрипка.
Ответ 2
Я не знал, что $modelValue был инициализирован NaN и столкнулся с аналогичной проблемой. Если для инициализации действительно требуется $modelValue, решение может быть просмотрено до тех пор, пока ему не будет присвоено новое значение:
.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();
}
//...
}
};
});
$watch возвращает функцию дерегистрации, поэтому ее можно незарегистрировать, как только новое значение присвоено $modelValue.
Ответ 3
Я думаю, вы можете также обернуть его в функцию ngModel.$render
.
Так же:
.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
Другой вариант (только если кто-то найдет этот вопрос здесь): просто завершите выполнение директивы в $timeout. Например, моя директива, которая его использует:
.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);
}
});
}}
})