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

提交表单时滚动动画完成后必填项提示框不显示

问题

我尝试仅使用Bootstrap类和required属性实现必填项提示框显示,但表单使用了submit事件的preventDefault()函数。提交空必填项时,required属性可正常触发滚动动画并定位光标,但“此字段为必填项”的提示框却不出现,仅在空文本框按回车时才显示。怀疑preventDefault()是问题根源,询问是否可手动设置滚动动画和提交时的提示框。

表单情况:

  • 约15个带对应label的for属性和input的name/id的复选框,JS中通过getElementById定义,用checked()验证返回1/0值;
  • 约10个文件输入框;
  • 少数邮箱、姓名等文本输入框;
    所有标签已闭合,属性和类验证正确,表单结构无误。

表单代码

<div class="row">
    <div class="col-3 d-none d-sm-none d-md-block" style="background-color: #0174bc;">
        
    </div>
    <div class="col-sm-12 col-md-9 px-3">
        <form id="certification_applicant_form" method="POST" class="was-validated">
            <hr>
            <!-- DATOS GENERALES DEL SOLICITANTE -->
            <h4 class="text-start">Datos generales</h4><br>
            
            <div class="row my-2">      
                <div class="col-sm-12 col-md-6 my-2">
                    <div class="row">
                        <div class="col-sm-12 col-md-4 my-2">
                            <label for="applicant_email"><b>*</b>Correo electrónico:</label>
                        </div>
                        <div class="col-sm-12 col-md-8 my-2">
                            <input class="form-control" placeholder="ejemplo@correo.com" type="email" id="applicant_email" name="applicant_email" required><br>
                        </div>
                    </div>
                </div>

                <div class="col-sm-12 col-md-6 my-2">
                    <div class="row">
                        <div class="col-sm-12 col-md-4 my-2">
                            <label for="applicant_name"><b>*</b>Nombre(s):</label>
                        </div>                                
                        <div class="col-sm-12 col-md-8 my-2">
                            <input class="form-control" placeholder="Nombre(s)" type="text" id="applicant_name" name="applicant_name" required><br>
                        </div>
                    </div>
                </div>

                <div class="col-sm-12 col-md-6 my-2">
                    <div class="row">
                        <div class="col-sm-12 col-md-4 my-2">
                            <label for="paternal_surname"><b>*</b>Apellido paterno:</label>
                        </div>

                        <div class="col-sm-12 col-md-8 my-2">
                            <input class="form-control" placeholder="Apellido paterno" type="text" id="paternal_surname" name="paternal_surname" required><br>
                        </div>
                    </div>
                </div>

                <div class="col-sm-12 col-md-6 my-2">
                    <div class="row">
                        <div class="col-sm-12 col-md-4 my-2">
                            <label for="maternal_surname"><b>*</b>Apellido materno:</label>
                        </div>                                
                        <div class="col-sm-12 col-md-8 my-2">
                            <input class="form-control" placeholder="Apellido materno" type="text" id="maternal_surname" name="maternal_surname" required><br>
                        </div>
                    </div>
                </div>
            </div>
            <hr>
            <!--  FORMACIÓN ACADÉMICA DEL SOLICITANTE   -->
            <div class="row my-2">
                <h4 class="text-start">Formación académica del solicitante</h4><br>
                <div class="col-sm-12 col-md-6">
                    <label for="main_degree"><b>*</b>Licenciatura obtenida:</label>
                    <input class="form-control"  placeholder="Licenciatura" type="text" id="main_degree" name="main_degree" required><br>
                </div>    
                <div class="col-12 col-sm-12 col-md-6 ">
                    <label for="main_degree_license"><b>*</b>Cédula profesional:</label>
                    <input maxlength="10" class="form-control" placeholder="Máximo 10 caracteres" type="text" id="main_degree_license" name="main_degree_license" required><br>
                </div>
            </div>
            <div class="row my-2">
                <p>Rama(s) de la propiedad intelectual en la que se ha desempeñado los últimos 3 años <br>*Marque todas las que apliquen</p><br>
                <div class="col-sm-12 col-md-6">
                    <label for="derechos_autor">
                        <input class="form-check-input" type="checkbox" name="derechos_autor" id="derechos_autor"> 
                        Derechos de autor
                    </label><br>
                    <label for="signos_distintivos">
                        <input class="form-check-input" type="checkbox" name="signos_distintivos" id="signos_distintivos"> 
                        Signos distintivos
                    </label><br>
                    <label for="invenciones">
                        <input class="form-check-input" type="checkbox" name="invenciones" id="invenciones"> 
                        Invenciones
                    </label><br>
                </div>
                <div class="col-sm-12 col-md-6">
                    <label for="secretos_industriales">
                        <input class="form-check-input" type="checkbox" id="secretos_industriales"> 
                        Secretos Industriales
                    </label><br>
                    <label for="litigio">
                        <input class="form-check-input" type="checkbox" id="litigio"> 
                        Litigio de derechos de propiedad intelectual
                    </label><br>
                    <label for="otro">
                        <input class="form-check-input" type="checkbox" id="otro"> 
                        Otro:
                    </label>
                    <input class="form-control" placeholder="Especifique el ramo" type="text" id="otro_text" name="otro_text" disabled>
                </div>
            </div>
            <div class="row my-2">
                <h4 class="text-start">Manifiesto de miembro activo en AMPPI</h4><br>
                <div class="col-9 text-justify">
                    <label for="verify_active_member">
                        Solicito verificación por parte de la Gerencia por haber sido miembro del consejo (incluyendo consejo ampliado)
                    </label><br>
                </div>
                <div class="col-3 my-auto">
                    <input class="form-check-input" type="checkbox" id="verify_active_member" name="verify_active_member"></div>
            </div>
            <div class="row my-2">
                <div class="col-9 text-justify">
                    <label for="active_member_cv_evidence">La evidencia consta en mi CV en extenso</label><br>
                </div>
                <div class="col-3 my-auto">
                    <input class="form-check-input" type="checkbox" id="active_member_cv_evidence" name="active_member_cv_evidence">
                </div>
            </div>        
            <div class="row my-2">
                <div class="col-9">
                    <label for="active_member_aditional_evidence">Tengo evidencia adicional</label><br>
                </div>
                <div class="col-3 my-auto">
                    <input class="form-check-input" type="checkbox" id="active_member_aditional_evidence" name="active_member_aditional_evidence">
                </div>
                <div id="additional_evidence_div" style="display: none;" class="col-12 my-2 text-center">
                    <label for="additional_evidence_file">Evidencia adicional:</label>
                    <input class="form-control" type="file" id="additional_evidence_file" name="additional_evidence_file" accept=".pdf, .jpg, .jpeg, .png"><br>
                </div>
            </div>
                    
            <div class="row text-center mx-2 my-4">
                <label for="max_files_link">Si tus archivos sobrepasan el máximo permitido en la plataforma, para las preguntas obligatorias por favor sube un archivo que contenga la liga además de incluirla en esta sección.</label>
                <input class="form-control" id="max_files_link" name="max_files_link"><br>
            </div>
            <div class="row text-center my-4">
                <label for="terms_and_privacy">
                    <input class="form-check-input" id="terms_and_privacy" type="checkbox" name="terms_and_privacy"> 
                    Acepto Reglas de Certificación AMPPI y Aviso de Privacidad<br>
                </label>
            </div>
            <div class="row text-center mx-2 mt-4">
                <div class="col-12">
                    <button class="btn btn-secondary" type="submit">Enviar solicitud</button>
                </div>
            </div>
        </form>
</div>

解决方案

核心原因

浏览器原生的表单验证提示(包括必填提示框)是在表单默认提交流程中触发的,preventDefault()阻止了默认提交,也就跳过了原生验证提示的触发环节,仅保留了滚动定位的行为。

具体实现

1. 手动触发完整原生验证

在submit事件监听函数中,先调用表单的checkValidity()方法触发完整验证(包含提示框),再根据结果处理后续逻辑:

document.getElementById('certification_applicant_form').addEventListener('submit', function(e) {
  // 触发完整原生验证
  const isValid = this.checkValidity();
  
  if (!isValid) {
    e.preventDefault();
    // 手动添加Bootstrap验证状态类,确保样式生效
    this.classList.add('was-validated');
  } else {
    // 验证通过,执行自定义提交逻辑
    // 若需要自定义提交,保留e.preventDefault();否则可移除
  }
});

2. 自定义滚动到无效字段(可选)

如果原生滚动不符合需求,可自行获取第一个无效元素并控制滚动:

const firstInvalid = document.querySelector('#certification_applicant_form :invalid');
if (firstInvalid) {
  // 平滑滚动到元素,添加偏移避免被顶部导航遮挡
  firstInvalid.scrollIntoView({ behavior: 'smooth', block: 'center' });
  // 聚焦到该元素
  firstInvalid.focus();
}

3. 复选框必填补充

若需要复选框(如条款同意)必填,需给其添加required属性,否则原生验证不会检查:

<input class="form-check-input" id="terms_and_privacy" type="checkbox" name="terms_and_privacy" required>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 07:35:57