[英]Input field caret position not getting set correctly
I have this directive down below for a <input type="text>
field 我在下面将这个指令用于
<input type="text>
字段
myApp.directive('onlyDecimal', function ()
{
return {
require: '?ngModel',
link: function(scope, element, attrs, ngModelCtrl)
{
if(!ngModelCtrl)
{
return;
}
ngModelCtrl.$parsers.push(function(val)
{
if (angular.isUndefined(val))
{
var val = "";
}
var clean = "";
if(val !== null)
{
clean = val.replace(/[^0-9\.]/g, "");
}
var start = element[0].selectionStart;
var end = element[0].selectionEnd + clean.length - val.length;
var negativeCheck = clean.split("-");
var decimalCheck = clean.split(".");
if(!angular.isUndefined(negativeCheck[1]))
{
negativeCheck[1] = negativeCheck[1].slice(0, negativeCheck[1].length);
clean = negativeCheck[0] + '-' + negativeCheck[1];
if(negativeCheck[0].length > 0)
{
clean = negativeCheck[0];
}
}
if(!angular.isUndefined(decimalCheck[1]))
{
decimalCheck[1] = decimalCheck[1].slice(0,2);
clean = decimalCheck[0] + "." + decimalCheck[1];
}
if (val !== clean)
{
ngModelCtrl.$setViewValue(clean);
ngModelCtrl.$render();
}
element[0].setSelectionRange(start, end);
return clean;
});
element.bind("keypress", function(event)
{
if(event.keyCode === 32)
{
event.preventDefault();
}
});
var decimalCount = 2;
var decimalPoint = ".";
ngModelCtrl.$render = function()
{
if (ngModelCtrl.$modelValue != null && ngModelCtrl.$modelValue >= 0)
{
if (typeof decimalCount === "number")
{
element.val(ngModelCtrl.$modelValue.toFixed(decimalCount).toString().replace(".", ","));
}
else
{
element.val(ngModelCtrl.$modelValue.toString().replace(".", ","));
}
}
}
element.on("change", function(e)
{
var floatValue = parseFloat(element.val().replace(",", "."));
if (!isNaN(floatValue) && typeof decimalCount === "number")
{
if (decimalCount === 0)
{
element.val(parseInt(floatValue));
}
else
{
var strValue = floatValue.toFixed(decimalCount);
element.val(strValue.replace(".", decimalPoint));
}
}
});
}
};
});
The purpose of this directive is to only allow numbers and 1 decimal in the field. 该指令的目的是在字段中仅允许数字和1个小数。
Let's say I have a value of 50.00
I then set the caret before the value which would be position 0 and I enter an invalid value of the key b
. 假设我有一个
50.00
的值,然后将插入号设置在位置0之前,然后输入密钥b
的无效值。 I set a console.log before I set the selection range and I get these values: 在设置选择范围之前,我先设置了console.log,然后得到了这些值:
START: 0 END: 1
START: 0 END: 0
It runs twice and it seems to still move the caret to the next position. 它运行两次,似乎仍将插入号移动到下一个位置。
There are at least two issues in your code that are causing problematic behavior: 您的代码中至少有两个问题会导致出现问题的行为:
In ngModelCtrl.$render
, you are checking the type of decimalCount
to determine if the $modelValue
is a number or a string. 在
ngModelCtrl.$render
,您正在检查decimalCount
的类型,以确定$modelValue
是数字还是字符串。 As soon as you start typing, ngModelCtrl.$modelValue
becomes a string, but your logic still attempts to call .toFixed()
on it, causing render to throw an exception, and preventing setSelectionRange
from being called by the parser. 一旦开始键入,
ngModelCtrl.$modelValue
就会变成一个字符串,但是您的逻辑仍然尝试在其上调用.toFixed()
,从而导致render引发异常,并阻止解析器调用setSelectionRange
。
Your logic that is swapping commas for decimals is not being used in your formatter. 格式化程序中未使用将逗号替换为小数的逻辑。 A value with a comma will come in, and the regex creating
clean
will remove it because it is expecting a decimal. 带有逗号的值将输入,而创建
clean
的正则表达式将删除它,因为它期望使用小数。 Once you fix that, you will have to also fix the comparison between val
and clean
at the end to swap decimals back to commas in clean
. 解决此问题后,还必须最后修复
val
和clean
之间的比较,以将小数交换回clean
逗号。
Overall, I would propose the following: 总体而言,我将提出以下建议:
if (typeof decimalCount === "number")
to if (typeof ngModelCtrl.$modelValue === "number")
if (typeof decimalCount === "number")
交换为if (typeof ngModelCtrl.$modelValue === "number")
clean
clean
之前,用小数替换所有逗号 clean
before comparing it back to the original val
. clean
比较回原来的前val
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.