如何为通用CRUD系统的JavaScript表单字段设置客户端输入验证
动态表单字段的客户端输入验证实现方案
基于你提供的CRUD代码结构,我们可以利用现有attribute_obj里的validations属性(比如name字段的required|minlength:3|maxlength:20|numeric),通过以下步骤实现客户端验证:
1. 解析验证规则
先写一个工具函数,把validations的字符串规则拆成可识别的结构化数据:
function parseValidationRules(validationStr) { if (!validationStr) return []; return validationStr.split('|').map(rule => { const [name, param] = rule.split(':'); return { name, param: param ? (isNaN(param) ? param : parseInt(param)) : null }; }); }
2. 修改buildRow函数,绑定验证逻辑
在创建完表单字段后,解析验证规则并给字段绑定输入、失焦事件,同时添加错误提示元素:
function buildRow(attribute_obj, currentRow) { attribute_obj.forEach(element => { for (const [input_element_key, input_element_value] of Object.entries(element)) { if(input_element_value.column_type!= "actions") { var buildFieldBox = document.createElement(input_element_value.column_type); for (const [input_attribute_key, input_attribute_value] of Object.entries(input_element_value.attributes)) { buildFieldBox.setAttribute(input_attribute_key, input_attribute_value); } // 新增:处理验证逻辑 const validationRules = parseValidationRules(input_element_value.attributes.validations); if (validationRules.length > 0) { // 创建错误提示容器 const errorSpan = document.createElement('span'); errorSpan.className = 'validation-error'; errorSpan.style.color = 'red'; errorSpan.style.fontSize = '0.8em'; errorSpan.style.display = 'none'; // 绑定验证触发事件 const runValidation = () => validateInput(buildFieldBox, validationRules, errorSpan); buildFieldBox.addEventListener('input', runValidation); buildFieldBox.addEventListener('blur', runValidation); // 提前把错误提示元素加入单元格(后续插入字段后会在同一单元格) const tempCell = document.createElement('td'); tempCell.appendChild(errorSpan); currentRow.appendChild(tempCell); } } // 原有switch逻辑保持不变 switch (input_element_value.column_type) { case "select": for (var i = 0; i < input_element_value.option_value.length; i++) { var option = document.createElement(input_element_value.column_option); option.value = input_element_value.option_value[i].value; option.text = input_element_value.option_value[i].text; buildFieldBox.appendChild(option); } break; case "actions": var currentCell = currentRow.insertCell(-1); for (const [key, value] of Object.entries(input_element_value.icons)) { var buildActionBox = document.createElement("a"); for (const [attribute_key, attribute_value] of Object.entries(value.attributes)) { buildActionBox.setAttribute(attribute_key, attribute_value); } if (input_element_value.icons) { var buildIconBox = document.createElement("i"); buildIconBox.setAttribute("class", "material-icons"); var text_icon = document.createTextNode(value.icon) buildIconBox.append(text_icon); buildActionBox.appendChild(buildIconBox); } currentCell.appendChild(buildActionBox); } break; default: break; } if(input_element_value.column_type!= "actions") { var currentCell = currentRow.insertCell(-1); currentCell.appendChild(buildFieldBox); // 把错误提示移到字段所在单元格 const errorSpan = currentRow.querySelector('.validation-error'); if (errorSpan) { currentCell.appendChild(errorSpan); currentRow.removeChild(errorSpan.parentElement); } } } }); }
3. 实现通用验证函数
写一个validateInput函数,根据规则检查输入值并更新错误提示:
function validateInput(field, rules, errorSpan) { let isValid = true; let errorMsg = ''; const value = field.value.trim(); for (const rule of rules) { switch (rule.name) { case 'required': if (!value) { isValid = false; errorMsg = '此字段为必填项'; } break; case 'minlength': if (value.length < rule.param) { isValid = false; errorMsg = `最少需要输入${rule.param}个字符`; } break; case 'maxlength': if (value.length > rule.param) { isValid = false; errorMsg = `最多输入${rule.param}个字符`; } break; case 'numeric': if (!/^\d+$/.test(value)) { isValid = false; errorMsg = '只能输入数字'; } break; // 可扩展更多规则,比如email、手机号等 } if (!isValid) break; } // 更新错误提示和字段样式 errorSpan.textContent = errorMsg; errorSpan.style.display = isValid ? 'none' : 'block'; field.classList.toggle('is-invalid', !isValid); return isValid; }
4. 提交时全局验证
如果有提交按钮,添加全局验证逻辑,确保所有字段都符合规则:
function validateAllFields() { const allFields = document.querySelectorAll('#myTableElements input, #myTableElements select'); let allValid = true; allFields.forEach(field => { const errorSpan = field.parentElement.querySelector('.validation-error'); if (!errorSpan) return; const validationStr = field.getAttribute('validations'); const rules = parseValidationRules(validationStr); if (rules.length > 0 && !validateInput(field, rules, errorSpan)) { allValid = false; } }); return allValid; } // 绑定提交按钮事件 document.getElementById('submitBtn')?.addEventListener('click', (e) => { if (!validateAllFields()) { e.preventDefault(); alert('请修正表单中的错误'); } });
5. 可选:添加验证样式
给验证不通过的字段加可视化样式,提升用户体验:
.is-invalid { border-color: #dc3545; box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); }
这套方案完全适配你现有的代码结构,支持实时输入验证和提交前全局检查,还能灵活扩展更多验证规则。
内容的提问来源于stack exchange,提问作者samurai
相关产品推荐
相关产品推荐

