验证数字输入并格式化数字输入

14
在使用C#的asp.net-mvc项目中,我使用了一个函数来为较大的数字添加逗号格式,例如1,000,000,感谢这篇文章
function numberWithCommas(str) {
    return str.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

问题是,我的输入已经被限制为只接受最小值为零的数字。

<input type="number" min="0" class="myclass" value="@somevalue" />

使用JS可能会遇到问题,因为它只需要数值输入。这让我想到了这样一个问题:如何使HTML的输入标签只接受数值?,这里也提供了JS解决方案。

我想知道是否有人开发了优雅的方法来格式化数字输入显示,同时验证数字输入,这里还有其他可用的选项吗?它不一定要纯粹是JS解决方案。


1
一种不同的方法,但您可能会对此插件感兴趣 - 使用@Html.NumericInputFor(m => m.SomeNumber)生成一个“透明”的文本框和一个“格式化”的底层。当您在文本框中按Tab键时,它变得不透明,并且只接受数字和小数分隔符。当您按Tab键时,您将看到格式化的数字。 - user3559349
你是否编写了自定义的 ModelBinder(如果没有,由于存在 “,” 字符,当您提交时它将无法绑定到您的模型)? - user3559349
1
这里为什么有C#和asp.net-mvc标签?看起来与问题无关(至少C#肯定是)。 - Evk
验证和重新格式化用户输入数据的过程充满了奇怪的边缘情况和用户烦恼,几乎不值得花费这样的精力。 - Jim Mischel
1
@Yvette,我不会添加答案(太复杂了),但我已经创建了这个DotNetFiddle来展示它的工作原理(<div class="numeric-container" ....>....</div>元素是由@Html.NumericInputFor(m => m.Price)方法为en-US文化创建的)。 - user3559349
1
@Yvette,它只是让你在控件之间进行制表和切换以查看它的工作原理 :).完整的答案还需要包括HtmlHelper扩展方法中的代码,这将使它变得太长,并且只包含源代码链接的答案将被删除 :)但是如果你愿意可以在你的答案中提到它。我希望这个周末能写好GitHub上的README文件 :) - user3559349
3个回答

7
您不能使用数字输入,因为JavaScript不认为格式化的数字是数字。解决方案是使用非数字输入,但过滤掉任何“有问题”的字符。在下面的示例中,我还处理了小数点分隔符,以防需要接受分数。当文本框正在编辑时,它还必须保留光标位置。我通过更新输入值而不失去光标位置来实现这一点。

function format(inp){
  var start = inp.selectionStart,  // get the selection start
      end   = inp.selectionEnd;    // and end, as per the linked post
  var s1=inp.value.split(",").length-1; //count the commas before edit
  inp.value=numberWithCommas(inp.value.replace(/,|[^\d.]/g,''));
  var s2=inp.value.split(",").length-s1-1; //count the commas after edit so as to know where to place the cursor, as the position changes, if there are new commas or some commas have been removed
  inp.setSelectionRange(start+s2, end+s2); // set the selection start and end, as per the linked post
}
function numberWithCommas(str) {
  var a=str.split('.');
  var p=/\B(?=(\d{3})+(?!\d))/g;
  if(a.length>1)
    return a[0].toString().replace(p, ",")+"."+a[1];
  else 
    return str.toString().replace(p, ",");
}
<input onkeyup="format(this)">


5
我可以回答你的第一个问题。
您可以禁用所有键,而不仅仅是数字键。
function isNumberKey(evt)  {
    var charCode = (evt.which) ? evt.which : event.keyCode;

    if (charCode != 43 && charCode > 31
      && (charCode < 48 || charCode > 57))
        return false;
    return true;

}

我还在jsfiddle上创建了工作演示


1
这不允许使用小数点或负号 :) - user3559349
呀,但这不是我需要的。你可以在代码中进行编辑(使用charCode)。 - Deep Shah
在 if 条件语句的第二行中编辑此代码 @StephenMuecke: " && (charCode < 47 || charCode > 57))"。现在您也可以放置分隔符。☺ - Deep Shah

2
程序流程:

通过on change事件获取输入并调用其他函数,通过Ajax POST传递数据。

$('.Amount').on("change", function (e) {
    var myInput = $(e.target);
    var input = this.value;
    // Remove any non digits (including commas) to pass value to controller.
    var Amount = validateInput(input);
    // Format the string to have commas every three digits 1,000,000 for display.
    var val = numberWithCommas(Amount);
    $(myInput).val(val);

    $.ajax({
        type: 'POST',
        dataType: "json",
        url: somesUrl + '/' + somethingelse,
        data: JSON.parse('{"Amount": "' + Amount + '"}'), // Amount is a nice format here and will not throw an error.
        // TODO etc
    });
});

去除所有非数字字符,若没有输入数字,则赋值为零。
var validateInput = function (input) {
    input = input.toString().replace(/[^0-9]/g, "");
    /* Remove leading zeros. */
    input = input.replace(/^0+/, '');
    if (input == "")
        input = 0;
    return input;
}

将输入格式化为带有逗号的 1,000,000,000。
function numberWithCommas(str) {
    return str.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

所以,即使用户输入带逗号的输入,例如1,734,567,它也可以正常工作,如果他们错位放置逗号,例如17,35,555,它仍然可以验证。
查看工作fiddle
我在尝试满足项目截止日期时找到了一个不错的解决方案,其中一部分是通过this answernicael解决的。
此解决方案在输入完成后而不是输入时检查输入,我选择更改事件,因为它只调用一次函数(类似于提交事件),然后一次性验证输入。删除任何逗号和非数字;通过删除ajax调用中的逗号来解决逗号格式问题,然后重新格式化为显示。有一个检查以删除前导零。
如果所有输入都是垃圾数据,我会将这个值替换为零,以防止空数据传递到控制器引起错误(这只是一种设计选择,也可以显示一个弹出消息)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接