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

Bootstrap 5分步表单问题:点击下一步仅验证当前标签页

解决Bootstrap 5分步表单的验证与提交问题

核心解决思路

  • 用单个主表单包裹所有分步内容,确保提交时能一次性发送所有字段数据
  • 点击「下一步」时,仅验证当前激活标签页内的必填字段
  • 借助Bootstrap 5的Tab组件API控制标签页切换逻辑

修正后的HTML代码

<div id="rootwizard">
    <ul class="nav nav-pills form-wizard-header mb-3">
        <li class="nav-item">
            <a href="#basic" data-bs-toggle="tab" class="nav-link rounded-0 pt-2 pb-2 active">
                <span>Info</span>
            </a>
        </li>
        <li class="nav-item">
            <a href="#first" data-bs-toggle="tab" class="nav-link rounded-0 pt-2 pb-2">
                <span>Device</span>
            </a>
        </li>
    </ul>

    <!-- 单个主表单包裹所有分步内容 -->
    <form id="multiStepForm" method="post" action="" class="form-horizontal">
        <div class="tab-content">
            <!-- 第一步标签页,默认激活 -->
            <div class="tab-pane fade show active" id="basic">
                <div class="row mb-3">
                    <label for="Client_Emp">Cliente/Empresa</label>
                    <div>
                        <input type="text" name="Client_Emp" id="Client_Emp" required />
                    </div>
                </div>
            </div>

            <!-- 第二步标签页 -->
            <div class="tab-pane fade" id="first">
                <div class="row mb-3">
                    <label for="cpu">CPU</label>
                    <div>
                        <!-- 修正原代码的id重复、多余</select>标签问题 -->
                        <input type="text" name="cpu" id="cpu" required />
                    </div>
                </div>
            </div>
        </div>

        <ul class="list-inline wizard mb-0">
            <li class="previous list-inline-item"><button type="button" class="btn btn-info">Previous</button></li>
            <li class="next list-inline-item float-end"><button type="button" class="btn btn-info">Next</button></li>
            <!-- 提交按钮默认隐藏,最后一步显示 -->
            <li class="submit list-inline-item float-end d-none"><button type="submit" class="btn btn-success">Submit</button></li>
        </ul>
    </form>
</div>

JavaScript逻辑(兼容Bootstrap 5)

document.addEventListener('DOMContentLoaded', function() {
    const form = document.getElementById('multiStepForm');
    const nextBtn = document.querySelector('.next');
    const prevBtn = document.querySelector('.previous');
    const submitBtn = document.querySelector('.submit');

    // 验证当前激活标签页的必填字段
    function validateCurrentTab() {
        const activePane = document.querySelector('.tab-pane.active');
        const requiredFields = activePane.querySelectorAll('[required]');
        let isValid = true;

        requiredFields.forEach(field => {
            if (!field.value.trim()) {
                isValid = false;
                // 触发原生浏览器验证提示
                field.reportValidity();
            }
        });

        return isValid;
    }

    // 下一步按钮逻辑
    nextBtn.addEventListener('click', function() {
        if (validateCurrentTab()) {
            const activeNav = document.querySelector('.nav-link.active');
            const nextNav = activeNav.closest('.nav-item').nextElementSibling?.querySelector('a');
            
            if (nextNav) {
                new bootstrap.Tab(nextNav).show();
                // 切换到最后一步时,替换按钮
                if (!nextNav.closest('.nav-item').nextElementSibling) {
                    nextBtn.classList.add('d-none');
                    submitBtn.classList.remove('d-none');
                }
                prevBtn.classList.remove('d-none');
            }
        }
    });

    // 上一步按钮逻辑
    prevBtn.addEventListener('click', function() {
        const activeNav = document.querySelector('.nav-link.active');
        const prevNav = activeNav.closest('.nav-item').previousElementSibling?.querySelector('a');
        
        if (prevNav) {
            new bootstrap.Tab(prevNav).show();
            // 回到第一步时隐藏上一步按钮
            if (!prevNav.closest('.nav-item').previousElementSibling) {
                prevBtn.classList.add('d-none');
            }
            nextBtn.classList.remove('d-none');
            submitBtn.classList.add('d-none');
        }
    });

    // 初始状态隐藏上一步按钮
    prevBtn.classList.add('d-none');
});

关键说明

  1. 单表单结构:所有分步字段都在同一个<form>内,提交时会自动收集所有带name属性的字段值,彻底解决多表单无法一次性提交的问题。
  2. 局部验证:validateCurrentTab函数仅针对当前激活标签页内的必填字段做校验,通过原生reportValidity()触发浏览器自带的验证提示,确保只验证当前步骤内容。
  3. 按钮状态控制:根据当前步骤自动切换「下一步/上一步/提交」按钮的显示状态,优化用户体验。
  4. 修复原代码问题:修正了输入框id重复、多余</select>标签的DOM错误,避免出现异常。

内容的提问来源于stack exchange,提问作者João Proença

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 04:24:32