Blazor自定义InputNumber组件:数字输入限制及报错处理
解决Blazor自定义InputNumber组件的event.preventDefault报错问题
报错原因
你遇到的event.preventDefault is not a function错误,是因为Blazor传递给JS的KeyboardEventArgs是框架封装后的对象,并非浏览器原生的键盘事件对象,所以没有preventDefault()方法。而且Blazor的键盘事件本身支持通过返回布尔值来控制是否阻止默认行为,完全不需要依赖JS来处理。
修复方案
- 移除JS中的
validateInput函数,把按键验证逻辑移到C#代码中,通过返回false来阻止非法按键的默认行为。 - 调整数值格式化逻辑,确保千分位用点、小数用逗号的显示格式符合需求。
- 优化输入值与decimal类型的转换逻辑,避免格式转换错误。
修改后的完整组件代码
@inherits InputNumber<decimal?> @using System.Globalization @using System.Text.RegularExpressions <input @attributes="AdditionalAttributes" id="@_id" class="@CssClass" value="@_stringValue" @onkeydown="OnKeyDown" @oninput="OnInput" @onchange="OnValueChanged" /> <script> window.formatNumberInput = function (value, allowDecimals) { let cleanedValue = value.replace(/[^0-9.,]/g, ''); // 统一将点替换为逗号,确保小数分隔符是逗号 cleanedValue = cleanedValue.replace(/\./g, ','); let parts = cleanedValue.split(','); // 千分位用点分隔 let integerPart = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, "."); let formattedValue = integerPart; if (allowDecimals && parts.length > 1) { // 保留两位小数 formattedValue += ',' + parts[1].substring(0, 2); } return formattedValue; } </script> @code { private string _id { get; set; } = Guid.NewGuid().ToString(); private string? _stringValue; private string? _currentValue; [Inject] IJSRuntime _jsRuntime { get; set; } // 自定义格式:千分位用点,小数用逗号 [Parameter] public string FormatString { get; set; } = "#.##0,00"; [Parameter] public bool AllowDecimals { get; set; } = true; protected override void OnParametersSet() { if (Value.HasValue) { // 使用自定义文化格式来匹配显示需求 var customCulture = (CultureInfo)CultureInfo.CurrentCulture.Clone(); customCulture.NumberFormat.NumberGroupSeparator = "."; customCulture.NumberFormat.NumberDecimalSeparator = ","; _stringValue = Value.Value.ToString(FormatString, customCulture); } else { _stringValue = null; } } private bool OnKeyDown(KeyboardEventArgs e) { // 允许的按键列表 var allowedKeys = new[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Backspace", "Tab", "Enter", "ArrowLeft", "ArrowRight" }; if (allowedKeys.Contains(e.Key)) { return true; } // 处理小数分隔符 if (AllowDecimals && (e.Key == "," || e.Key == ".")) { // 确保输入框中最多只有一个小数分隔符 if (_stringValue?.Contains(',') == false) { return true; } } // 阻止非法按键的默认行为 return false; } private async Task OnInput(ChangeEventArgs e) { _currentValue = e.Value?.ToString(); var formattedValue = await _jsRuntime.InvokeAsync<string>("formatNumberInput", _currentValue, AllowDecimals); _stringValue = formattedValue; // 将显示格式转换为decimal可识别的格式:去掉千分位点,将小数逗号换成点 var rawValue = formattedValue.Replace(".", "").Replace(",", "."); if (decimal.TryParse(rawValue, out var result)) { Value = result; await ValueChanged.InvokeAsync(Value); } } private async Task OnValueChanged(ChangeEventArgs e) { await OnInput(e); } }
关键修改说明
- 按键验证逻辑:移到C#的
OnKeyDown方法中,通过返回false直接阻止非法按键,避免了JS与Blazor事件对象的不兼容问题。 - 格式化文化适配:在
OnParametersSet中创建自定义CultureInfo,指定千分位为点、小数位为逗号,确保初始值显示正确。 - JS格式化优化:统一将输入中的点替换为逗号,避免出现多个小数分隔符的问题,保证格式化后的字符串符合要求。
内容的提问来源于stack exchange,提问作者user1531040
相关产品推荐
相关产品推荐

