You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core MVC表单字段导航异常求助:TAB与自动跳转问题

问题描述

现有5个表单字段:字段1为数字字段,字段2-5为字母字段。需求如下:

  • 按TAB可从数字字段跳转到第一个字母字段,按SHIFT+TAB可从字母字段返回数字字段;
  • 字母字段间禁用正向TAB跳转,但允许反向SHIFT+TAB跳转;
  • 字母字段输入满4个字符时自动跳转到下一个字段。

当前已实现字母字段满字符自动跳转,且禁用了TAB跳转,但存在两个问题:

  1. 无法从数字字段通过TAB跳转到第一个字母字段;
  2. 按SHIFT+TAB返回时,若当前字母字段已填满4个字符,焦点会立刻跳回该字段,无法正常返回。

现有代码如下:

@section Scripts
{
<script>
    $(".form-control").keydown(function (e) {
        if (e.keyCode === 9) { 
            if (e.shiftKey) {                     
            } else {
                e.preventDefault(); 

                if (this.value.length === this.maxLength) {                        
                    $(this).parent().next().find('.form-control').focus();
                }
            }
        }
    });

    $(".form-control").keyup(function () {
        if (this.value.length === this.maxLength) {
            var $next = $(this).parent().next().find('.form-control');
            if ($next.length)
                $next.focus();
            else
                $(this).blur();
        }
    });
</script>
}

<div class="row">
 <div class="col-sm-6">
    <label class="col-form-label">@HtmlLocalizer["Number"]</label>
 </div>
 <div class="row">
    <div class="col-sm-3">
    @Html.TextBoxFor(model => model.Number, new { oninput = "javascript: this.value = this.value.replace(/[^0-9]/g, '')", @class = "form-control"})                    
    </div>
    @Html.ValidationMessageFor(model => model.Number, "", new { @class = "text-danger" })
 </div>
</div>           
            
<div class="row">
<div class="col-sm-3">
    <input class="form-control" asp-for="LetterField1" maxlength="4" />
</div>
<div class="col-sm-3">
    <input class="form-control" asp-for="LetterField2" maxlength="4" />
</div>
<div class="col-sm-3">
    <input class="form-control" asp-for="LetterField3" maxlength="4" />
</div>
<div class="col-sm-3">
    <input class="form-control" asp-for="LetterField4" maxlength="4" />
</div>
</div>
问题分析与修复方案

核心错误点

  1. 全局阻止TAB默认行为:代码对所有.form-control元素(包括数字字段)的正向TAB都执行e.preventDefault(),直接破坏了数字字段到字母字段的原生TAB跳转逻辑。
  2. 自动跳转与SHIFT+TAB冲突:当按SHIFT+TAB从满字符的字母字段返回时,keyup事件会检测到字段长度等于maxlength,立刻触发自动跳转,将焦点强制拉回当前字段,覆盖了SHIFT+TAB的反向跳转操作。

修复后的代码

1. 修改JavaScript逻辑

@section Scripts
{
<script>
    // 仅对字母字段绑定TAB控制逻辑
    $(".letter-field").keydown(function (e) {
        if (e.keyCode === 9) { 
            if (!e.shiftKey) { 
                // 仅阻止字母字段的正向TAB默认行为
                e.preventDefault(); 
                if (this.value.length === this.maxLength) {                        
                    $(this).parent().next().find('.letter-field').focus();
                }
            }
            // 反向SHIFT+TAB保留原生行为,不做干预
        }
    });

    $(".letter-field").keyup(function (e) {
        // 排除SHIFT、TAB功能键触发的keyup,避免与跳转冲突
        if ([16, 9].includes(e.keyCode)) return;
        
        if (this.value.length === this.maxLength) {
            var $next = $(this).parent().next().find('.letter-field');
            if ($next.length)
                $next.focus();
            else
                $(this).blur();
        }
    });
</script>
}

2. 修改HTML结构(给字母字段添加专属类)

<div class="row">
<div class="col-sm-3">
    <input class="form-control letter-field" asp-for="LetterField1" maxlength="4" />
</div>
<div class="col-sm-3">
    <input class="form-control letter-field" asp-for="LetterField2" maxlength="4" />
</div>
<div class="col-sm-3">
    <input class="form-control letter-field" asp-for="LetterField3" maxlength="4" />
</div>
<div class="col-sm-3">
    <input class="form-control letter-field" asp-for="LetterField4" maxlength="4" />
</div>
</div>

修复说明

  • 给字母字段单独添加letter-field类,将TAB控制逻辑的作用范围限制在字母字段内,数字字段保留原生TAB跳转能力,解决无法从数字字段跳转到字母字段的问题。
  • 在keyup事件中排除SHIFT(键码16)和TAB(键码9)的触发,避免用户按SHIFT+TAB返回时,自动跳转逻辑干扰反向跳转操作,解决焦点被强制拉回的问题。
  • 保留原有的满字符自动跳转逻辑,确保字母字段的正向自动跳转功能正常。

内容的提问来源于stack exchange,提问作者Kojote

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 06:05:56