动态表单验证需求及代码修复:空字段提示与按钮启用控制
动态表单验证功能实现与修复
需求说明
- 空字段验证:表单存在空输入项时,弹出提示“存在空字段”,并将焦点定位到第一个空输入项;所有字段填写完整后,弹出提示“填写成功”。
- 保存按钮规则:仅当第二个表格中已添加条目,且表单所有字段(包括动态生成的字段)均填写完整时,才启用“Guardar”按钮;若第二个表格无条目,即使搜索框及相邻字段有内容,按钮仍保持禁用。
- 修复当前无法正常工作的
validations()函数,实现上述验证逻辑。
修复后的完整代码
HTML 代码
<html> <head> <title>Untitled-2</title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.8.0/css/bulma.min.css"> </head> <body> <section class="section"> <div class="tabs"> <ul class="tabs-menu"> <li class="is-active" data-target="first-tab"><a>Tab one</a></li> <li data-target="second-tab"><a>Tab two</a></li> </ul> </div> <div class="tab-content" id="first-tab"> <table id="articulos"class="table"> <thead> <tr> <TH>id </TH> <TH>id del producto</TH> <TH>cantidad_disponible</TH> <TH>talla zapatos</TH> <TH>Añadir</TH> <TH>Añadir</TH> </tr> </thead> <tbody id="productos_content"> <tr class="tr"> <td class="id_n">15<td> <td class="cantidad_disponible"> 3</td> <td class="talla"> 36</td> <td class="td"><button id="15" onclick="add(15)" class="button">Añadir</button></td> </tr> <tr class="tr"> <td class="id_n">1<td> <td class="cantidad_disponible"> 7</td> <td class="talla"> 40</td> <td class="td"><button id="15" onclick="add(1)" class="button">Añadir</button></td> </tr> </tbody> </table> </div> <div class="tab-content" id="second-tab"> <div class="shopping-cart-items shoppingCartItemsContainer"> <form id="form2" onsubmit="return validations(this)"> <input type="text" name="campo" id="campo" class="form-control" placeholder="buscar" required> <input type="text" name="content" id="content" class="form-control"> <input type="submit" id="guardardatos" value="Guardar" disabled /> <table id="tabla" class="table"> <tr> <TH>id</TH> <TH>id del producto</TH> <TH>cantidad_disponible</TH> <TH>talla zapatos</TH> <TH>cantidad </TH> <TH>precio </TH> </tr> <tbody id="carrito_content" class="tbody"> </tbody> </table> <div class="float-right"> Total:<input type="text" id="resultado_total" value="0" disabled > </input> </div> </form> </div> </div> </body> <script> const tabSystem = { init(){ document.querySelectorAll('.tabs-menu').forEach(tabMenu => { Array.from(tabMenu.children).forEach((child, ind) => { child.addEventListener('click', () => { tabSystem.toggle(child.dataset.target); }); if(child.className.includes('is-active')){ tabSystem.toggle(child.dataset.target); } }); }); }, toggle(targetId){ document.querySelectorAll('.tab-content').forEach(contentElement=>{ contentElement.style.display = contentElement.id === targetId ? 'block' : 'none'; document.querySelector(`[data-target="${contentElement.id}"]`).classList[contentElement.id === targetId ? 'add' : 'remove']('is-active'); }) }, }; tabSystem.init() </script> </html>
JavaScript 代码
function updateCantidadNuevo(input) { if(input.checkValidity()){ input.setAttribute("data-oldvalue", input.value); } else{ input.value = input.getAttribute("data-oldvalue") || input.min; } // 每次修改数量后检查表单有效性 checkFormValidity(); } function add(id, cantidad=1){ let input = tbody.querySelector('.ItemCarrito>.form__element-input_cantidad>#shoppingCartItemQuantity_'+id); if (input === null) { return; } if (typeof input.value === 'undefined' || input.value === null) { input.value = cantidad; } else { input.value = (input.valueAsNumber + cantidad); } updateCantidadNuevo(input); } const tbody = document.querySelector('#second-tab >.shoppingCartItemsContainer > #form2 >#tabla >.tbody'); const saveButton = document.getElementById('guardardatos'); const form = document.getElementById('form2'); // 监听删除按钮事件 tbody.addEventListener('click', (e) => { if(e.target.classList.contains('delete')){ e.target.closest('.ItemCarrito').remove(); checkFormValidity(); } }); // 监听表单输入事件,实时检查有效性 form.addEventListener('input', checkFormValidity); const addToShoppingCartButtons = document.querySelectorAll('#first-tab > #articulos > tbody > tr > .td > .button'); addToShoppingCartButtons.forEach((addToCartButton) => { addToCartButton.addEventListener('click', addToCartClicked); }); function addToCartClicked(event) { const button = event.target; const item = button.closest('.tr'); const id_prod = item.querySelector('.id_n').textContent; const cantidad_disponible = item.querySelector('.cantidad_disponible').textContent; const talla = item.querySelector('.talla').textContent; addItemToShoppingCart(id_prod, cantidad_disponible, talla); } function addItemToShoppingCart(id_prod,cantidad_disponible,talla) { const elementsTitle = document.getElementsByClassName('title'); for (let i = 0; i < elementsTitle.length; i++) { if (elementsTitle[i].innerText === id_prod) { return; } } const tr = document.createElement('tr') tr.classList.add('ItemCarrito') tr.setAttribute("id", `tr_${id_prod}`); const Content = ` <th scope="row">${id_prod}</th> <td class="table__productos"> <input id="id_productos_${id_prod}" type="text" value="${id_prod}" class="id_productos" style="border: none; border-color: transparent;outline: 0;width: 40px;"> <h6 id="title_${id_prod}" class="title" hidden>${id_prod}</h6> </td> <td class="table__cantidad_disponible"> <input id="cantidad_disponible_${id_prod}" type="text" value="${cantidad_disponible}" class="cantidad_disponible" style="border: none; border-color: transparent;outline: 0;width: 40px;" > </td> <td class="table__talla"> <input id="talla_${id_prod}" type="text" value="${talla}" class="talla" style="border: none; border-color: transparent;outline: 0;width: 40px;"> </td> <td class="form__element-input_cantidad"> <input id="shoppingCartItemQuantity_${id_prod}" max="${cantidad_disponible}" class="shopping-cart-quantity-input cantidad" type="number" value="1" min="1"> </td> <td class="form__element-input_precio"> <input name="precio_${id_prod}" id="precio_${id_prod}" type="text" class="precio" min="0"> </td> <td class="table__delete"> <button class="delete btn btn-danger">x</button> </td> ` tr.innerHTML = Content; tbody.append(tr); // 添加条目后检查表单有效性 checkFormValidity(); } // 检查表单是否有效,控制保存按钮状态 function checkFormValidity() { const hasItems = tbody.querySelectorAll('.ItemCarrito').length > 0; if(!hasItems){ saveButton.disabled = true; return; } // 获取所有需要验证的输入字段:表单内所有input,排除disabled的 const allInputs = form.querySelectorAll('input:not([disabled])'); let allFilled = true; allInputs.forEach(input => { if(input.value.trim() === ''){ allFilled = false; } }); saveButton.disabled = !allFilled; } // 修复后的表单提交验证函数 function validations(form) { // 获取所有非disabled的输入字段 const allInputs = form.querySelectorAll('input:not([disabled])'); let firstEmptyField = null; for(const input of allInputs){ if(input.value.trim() === ''){ firstEmptyField = input; break; } } if(firstEmptyField){ firstEmptyField.focus(); alert('存在空字段'); return false; } alert('填写成功'); // 这里可以添加表单提交逻辑,比如form.submit() return false; // 暂时阻止默认提交,方便测试 }
关键修复与实现说明
HTML 修改
- 给
content输入框添加name属性,确保验证时能识别该字段 - 初始设置保存按钮为
disabled状态
- 给
空字段验证修复
- 重写
validations()函数,遍历表单内所有非禁用的输入字段,找到第一个空字段并聚焦,弹出对应提示 - 所有字段填写完整时,弹出“填写成功”提示
- 重写
保存按钮状态控制
- 添加
checkFormValidity()函数,用于检查:- 第二个表格是否有条目(通过
.ItemCarrito元素数量判断) - 所有输入字段(含动态生成的
precio等字段)是否都已填写
- 第二个表格是否有条目(通过
- 在添加条目、删除条目、输入内容修改时,自动调用
checkFormValidity()更新按钮状态 - 若表格无条目,直接禁用按钮;有条目但存在空字段时也禁用,只有全部满足条件才启用
- 添加
动态字段处理
- 动态生成的
precio字段添加name属性,确保被纳入验证范围 - 监听删除按钮事件,删除条目后重新检查表单有效性
- 动态生成的
内容的提问来源于stack exchange,提问作者FelipeDeveloper
相关产品推荐
相关产品推荐

