【问题标题】:Input field caret position not getting set correctly输入字段插入符号位置未正确设置
【发布时间】:2018-04-11 16:26:19
【问题描述】:

我在下面有一个<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));
                    }
                }
            });
        }
    };
});

该指令的目的是在字段中只允许数字和 1 个小数。

假设我有一个50.00 的值,然后我将插入符号设置在位置0 的值之前,并输入键b 的无效值。我在设置选择范围之前设置了一个 console.log,我得到了这些值:

START: 0 END: 1
START: 0 END: 0

它运行了两次,似乎仍然将插入符号移动到下一个位置。

【问题讨论】:

    标签: javascript angularjs input caret


    【解决方案1】:

    您的代码中至少有两个问题会导致问题行为:

    1. ngModelCtrl.$render 中,您正在检查decimalCount 的类型以确定$modelValue 是数字还是字符串。一旦你开始输入,ngModelCtrl.$modelValue 就会变成一个字符串,但你的逻辑仍然会尝试在其上调用 .toFixed(),从而导致渲染抛出异常,并阻止 setSelectionRange 被解析器调用。

    2. 格式化程序中没有使用逗号换小数的逻辑。一个带逗号的值将进入,创建clean 的正则表达式将删除它,因为它需要一个小数。解决此问题后,您还必须在末尾修复valclean 之间的比较,以将clean 中的小数换回逗号。

    总的来说,我会提出以下建议:

    1. if (typeof decimalCount === "number") 交换为if (typeof ngModelCtrl.$modelValue === "number")
    2. 在生成clean之前用小数替换所有逗号
    3. clean 中的所有小数替换为逗号,然后再将其与原始val 进行比较。

    【讨论】:

      猜你喜欢
      • 2010-10-06
      • 2014-04-29
      • 2021-12-18
      • 2016-08-13
      • 2011-08-22
      • 2013-07-25
      • 1970-01-01
      • 1970-01-01
      • 2017-12-06
      相关资源
      最近更新 更多