bootstrapValidate valid hidden dom

本文介绍如何使用bootstrapvalidate插件实现跨标签页的表单验证。通过调整excluded参数,确保即使在切换标签页时也能正确检测到所有表单字段的状态。

bootstrapvalidate 插件在bootstrap标签页的使用

 

假设有两个标签页tab1, tab2,tab1和tab2都用bootstrapvalidate验证各自的form表单,我想在任何一个页面,触发验证条件时,也能检测另一个标签页的表单数据;这就需要设置excluded参数的值;默认的excluded的值是”[':disabled', ':hidden', ':not(:visible)']“,所以如果要想验证hidden或disabled掉的form元素,可以把excluded值置为空,即excluded: ""

 

官方文档:http://formvalidation.io/settings/

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>学生信息管理系统</title> <!-- 外部资源引入 --> <script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css"> <!-- 样式模块:按功能划分 --> <style> /* 1. 全局基础样式 */ * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; overflow-x: hidden; background-color: #f8f9fa; } /* 2. 侧边栏样式 */ .sidebar { position: fixed; top: 0; left: 0; height: 100vh; width: 220px; background-color: #2c3e50; color: #fff; padding-top: 20px; box-shadow: 2px 0 5px rgba(0,0,0,0.1); transition: all 0.3s ease; z-index: 1000; } .sidebar-header { text-align: center; padding: 0 20px 20px; border-bottom: 1px solid #34495e; margin-bottom: 20px; } .sidebar-header h2 { font-size: 1.5rem; color: #ecf0f1; } .nav-menu { list-style: none; } .nav-item .nav-link { display: flex; align-items: center; padding: 12px 20px; color: #bdc3c7; text-decoration: none; transition: all 0.3s; } .nav-item .nav-link:hover, .nav-item .nav-link.active { background-color: #34495e; color: #fff; padding-left: 25px; } .nav-link i { margin-right: 10px; width: 20px; text-align: center; } /* 3. 主内容区样式 */ .main-content { margin-left: 220px; padding: 30px; transition: all 0.3s ease; min-height: 100vh; } .content-header { margin-bottom: 20px; padding-bottom: 15px; border-bottom: 1px solid #e9ecef; } .content-header h1 { font-size: 1.8rem; color: #2c3e50; } /* 4. 功能组件样式 */ .search-container { margin-bottom: 20px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; } #searchInput { flex-grow: 1; max-width: 400px; } .operation-btn { margin: 0 5px; } .debug-info { margin-top: 20px; padding: 15px; background-color: #f8f9fa; border-radius: 5px; display: none; border: 1px solid #e9ecef; } /* 5. 模态框样式 */ .modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1050; align-items: center; justify-content: center; } .modal-content { background: #fff; padding: 25px; width: 100%; max-width: 500px; border-radius: 8px; box-shadow: 0 5px 15px rgba(0,0,0,0.2); position: relative; } .close { position: absolute; top: 15px; right: 20px; font-size: 24px; cursor: pointer; color: #6c757d; transition: color 0.2s; } .close:hover { color: #dc3545; } /* 6. 提示消息样式 */ .status-message { position: fixed; top: 20px; right: 20px; padding: 15px 20px; border-radius: 5px; color: #fff; z-index: 2000; display: none; box-shadow: 0 3px 10px rgba(0,0,0,0.2); } .status-success { background-color: #28a745; } .status-error { background-color: #dc3545; } /* 7. 表格样式 */ .table-responsive { background-color: #fff; border-radius: 8px; box-shadow: 0 2px 5px rgba(0,0,0,0.05); overflow: hidden; } /* 8. 响应式适配 */ @media (max-width: 768px) { .sidebar { width: 70px; } .sidebar-header h2, .nav-link span { display: none; } .nav-link { justify-content: center; padding: 15px 0 !important; } .nav-link i { margin-right: 0; font-size: 1.2rem; } .main-content { margin-left: 70px; padding: 15px; } } </style> </head> <body> <!-- 状态提示组件 --> <div class="status-message" id="statusMessage"></div> <!-- 侧边栏导航 --> <div class="sidebar"> <div class="sidebar-header"> <h2>学生管理系统</h2> </div> <ul class="nav-menu"> <li class="nav-item"> <a href="#" class="nav-link active" data-page="student-list"> <i class="bi bi-people"></i> <span>学生信息管理</span> </a> </li> <li class="nav-item"> <a href="#" class="nav-link" data-page="statistics"> <i class="bi bi-bar-chart"></i> <span>数据统计分析</span> </a> </li> <li class="nav-item"> <a href="#" class="nav-link" data-page="settings"> <i class="bi bi-gear"></i> <span>系统设置</span> </a> </li> </ul> </div> <!-- 主内容区域 --> <div class="main-content"> <div class="content-header"> <h1>学生信息列表</h1> </div> <!-- 搜索与操作按钮区 --> <div class="search-container"> <input type="text" id="searchInput" class="form-control" placeholder="请输入学号或姓名搜索..."> <button id="searchBtn" class="btn btn-secondary">搜索</button> <button id="resetBtn" class="btn btn-outline-secondary">重置</button> <button id="addBtn" class="btn btn-primary ms-auto">新增学生</button> <button id="toggleDebug" class="btn btn-info">显示调试</button> </div> <!-- 学生表格 --> <div class="table-responsive"> <table class="table table-bordered table-striped"> <thead class="table-light"> <tr> <th>学号</th> <th>姓名</th> <th>密码</th> <th>年级</th> <th>专业</th> <th>电话</th> <th>操作</th> </tr> </thead> <tbody id="studentTable"> <!-- 数据通过JS动态渲染 --> </tbody> </table> </div> <!-- 调试信息区 --> <div class="debug-info" id="debugInfo"> <h5 class="fw-bold">调试信息</h5> <pre id="debugLog" class="mb-0"></pre> </div> </div> <!-- 新增/编辑模态框 --> <div id="studentModal" class="modal"> <div class="modal-content"> <span class="close">×</span> <h3 id="modalTitle" class="mb-4">新增学生</h3> <form id="studentForm"> <input type="hidden" id="studentId"> <!-- 隐藏ID,用于编辑 --> <!-- 姓名输入 --> <div class="mb-3"> <label for="stuname" class="form-label">姓名 <span class="text-danger">*</span></label> <input type="text" class="form-control" id="stuname" required> <div class="text-danger small mt-1" id="stunameError" style="display: none;">请输入姓名</div> </div> <!-- 密码输入 --> <div class="mb-3"> <label for="password" class="form-label">密码 <span class="text-danger">*</span></label> <input type="text" class="form-control" id="password" required> <div class="text-danger small mt-1" id="passwordError" style="display: none;">请输入密码</div> </div> <!-- 年级输入 --> <div class="mb-3"> <label for="grade" class="form-label">年级 <span class="text-danger">*</span></label> <input type="text" class="form-control" id="grade" required placeholder="如:2023"> <div class="text-danger small mt-1" id="gradeError" style="display: none;">请输入年级</div> </div> <!-- 专业输入 --> <div class="mb-3"> <label for="major" class="form-label">专业 <span class="text-danger">*</span></label> <input type="text" class="form-control" id="major" required> <div class="text-danger small mt-1" id="majorError" style="display: none;">请输入专业</div> </div> <!-- 电话输入 --> <div class="mb-3"> <label for="phone" class="form-label">电话 <span class="text-danger">*</span></label> <input type="tel" class="form-control" id="phone" required placeholder="如:13800138000"> <div class="text-danger small mt-1" id="phoneError" style="display: none;">请输入有效电话</div> </div> <!-- 提交按钮 --> <button type="submit" class="btn btn-success w-100">保存</button> </form> </div> </div> <script> // 1. 系统配置(集中管理,便于修改) const SystemConfig = { API_BASE_URL: "http://localhost:8080", // 后端接口根地址 ID_FIELD: "studentId", // 学生ID字段名(与后端一致) STATUS_DURATION: 3000 // 提示消息显示时长(毫秒) }; // 2. DOM元素缓存(避免重复查询DOM) const DOM = { // 表格相关 studentTable: $("#studentTable"), searchInput: $("#searchInput"), searchBtn: $("#searchBtn"), resetBtn: $("#resetBtn"), addBtn: $("#addBtn"), // 模态框相关 studentModal: $("#studentModal"), modalTitle: $("#modalTitle"), studentForm: $("#studentForm"), studentId: $("#studentId"), stuname: $("#stuname"), password: $("#password"), grade: $("#grade"), major: $("#major"), phone: $("#phone"), // 提示与调试 statusMessage: $("#statusMessage"), toggleDebug: $("#toggleDebug"), debugInfo: $("#debugInfo"), debugLog: $("#debugLog"), closeBtn: $(".close") }; // 3. 工具函数(提取公共逻辑) const Tool = { /** * 日志记录(控制台+页面调试区) * @param {string} message - 日志内容 */ log: function(message) { const time = new Date().toLocaleTimeString(); const logText = `[${time}] ${message}\n`; // 页面调试区显示 DOM.debugLog.prepend(logText); // 控制台显示 console.log(`[调试] ${message}`); }, /** * 显示状态提示 * @param {string} message - 提示内容 * @param {boolean} isSuccess - 是否成功(true=绿色,false=红色) */ showStatus: function(message, isSuccess = true) { DOM.statusMessage .text(message) .removeClass("status-success status-error") .addClass(isSuccess ? "status-success" : "status-error") .fadeIn(300); // 自动隐藏 setTimeout(() => { DOM.statusMessage.fadeOut(500); }, SystemConfig.STATUS_DURATION); }, /** * AJAX错误统一处理 * @param {string} defaultMsg - 默认错误提示 * @returns {function} 错误处理函数 */ handleAjaxError: function(defaultMsg) { return function(xhr) { let errorMsg = defaultMsg; try { const res = JSON.parse(xhr.responseText); errorMsg = `${defaultMsg}:${res.message || res.msg || xhr.statusText}`; } catch (e) { errorMsg = `${defaultMsg}:${xhr.status} - ${xhr.statusText}`; } Tool.log(`AJAX错误:${errorMsg}`); Tool.showStatus(errorMsg, false); }; } }; // 4. 业务逻辑(核心功能) const StudentService = { /** * 初始化页面(入口函数) */ init: function() { Tool.log("页面加载完成,开始初始化"); this.bindEvents(); // 绑定所有事件 this.loadStudents(); // 加载学生列表 }, /** * 绑定所有页面事件 */ bindEvents: function() { // 导航栏切换 $(".nav-link").on("click", function(e) { e.preventDefault(); $(".nav-link").removeClass("active"); $(this).addClass("active"); }); // 搜索按钮 DOM.searchBtn.on("click", () => this.searchStudents()); // 重置按钮 DOM.resetBtn.on("click", () => { DOM.searchInput.val(""); this.loadStudents(); }); // 回车键搜索 DOM.searchInput.on("keypress", (e) => { if (e.which === 13) this.searchStudents(); }); // 新增按钮 DOM.addBtn.on("click", () => this.openModalForAdd()); // 关闭模态框 DOM.closeBtn.on("click", () => this.closeModal()); // 点击模态框外部关闭 $(window).on("click", (e) => { if (e.target === DOM.studentModal[0]) this.closeModal(); }); // 表单提交(新增/编辑) DOM.studentForm.on("submit", (e) => { e.preventDefault(); this.submitForm(); }); // 调试开关 DOM.toggleDebug.on("click", () => { DOM.debugInfo.toggle(); }); // 表格操作按钮(动态渲染后绑定) DOM.studentTable.on("click", ".edit-btn", (e) => { const id = $(e.currentTarget).data("id"); this.openModalForEdit(id); }); DOM.studentTable.on("click", ".delete-btn", (e) => { const id = $(e.currentTarget).data("id"); this.deleteStudent(id); }); }, /** * 加载所有学生列表 */ loadStudents: function() { Tool.log("开始加载学生数据"); $.ajax({ url: `${SystemConfig.API_BASE_URL}/student`, type: "GET", dataType: "json", success: (students) => { Tool.log(`成功加载 ${students.length} 条学生数据`); this.renderTable(students); }, error: Tool.handleAjaxError("加载学生列表失败") }); }, /** * 搜索学生(按学号/姓名) */ searchStudents: function() { const keyword = DOM.searchInput.val().trim(); Tool.log(`搜索关键词:${keyword}`); if (!keyword) { this.loadStudents(); return; } $.ajax({ url: `${SystemConfig.API_BASE_URL}/student/search`, type: "GET", data: { keyword }, dataType: "json", success: (students) => { Tool.log(`搜索到 ${students.length} 条匹配数据`); this.renderTable(students); }, error: Tool.handleAjaxError("搜索学生失败") }); }, /** * 渲染学生表格 * @param {Array} students - 学生数据数组 */ renderTable: function(students) { DOM.studentTable.empty(); // 空数据提示 if (students.length === 0) { DOM.studentTable.append(` <tr> <td colspan="7" class="text-center py-3 text-muted"> 没有找到匹配的学生信息 </td> </tr> `); return; } // 渲染数据行 students.forEach(student => { const id = student[SystemConfig.ID_FIELD] || "未知"; const row = ` <tr> <td>${id}</td> <td>${student.stuname || "未知"}</td> <td>******</td> <!-- 密码脱敏 --> <td>${student.grade || "未知"}</td> <td>${student.major || "未知"}</td> <td>${student.phone || "未知"}</td> <td> <button class="btn btn-warning btn-sm operation-btn edit-btn" data-id="${id}">编辑</button> <button class="btn btn-danger btn-sm operation-btn delete-btn" data-id="${id}">删除</button> </td> </tr> `; DOM.studentTable.append(row); }); }, /** * 打开新增学生模态框 */ openModalForAdd: function() { Tool.log("打开新增学生模态框"); // 重置表单 DOM.studentForm[0].reset(); DOM.studentId.val(""); // 隐藏错误提示 this.hideAllErrors(); // 设置标题并显示 DOM.modalTitle.text("新增学生"); DOM.studentModal.css("display", "flex"); }, /** * 打开编辑学生模态框 * @param {string} id - 学生ID */ openModalForEdit: function(id) { if (!id || id === "未知") { Tool.showStatus("学生ID无效", false); return; } Tool.log(`打开编辑模态框,学生ID:${id}`); $.ajax({ url: `${SystemConfig.API_BASE_URL}/student/${id}`, type: "GET", dataType: "json", success: (student) => { if (!student) { Tool.showStatus(`未找到ID为${id}的学生`, false); return; } // 填充表单数据 DOM.studentId.val(student[SystemConfig.ID_FIELD] || ""); DOM.stuname.val(student.stuname || ""); DOM.password.val(student.password || ""); DOM.grade.val(student.grade || ""); DOM.major.val(student.major || ""); DOM.phone.val(student.phone || ""); // 隐藏错误提示并显示模态框 this.hideAllErrors(); DOM.modalTitle.text("编辑学生"); DOM.studentModal.css("display", "flex"); }, error: Tool.handleAjaxError(`加载ID为${id}的学生数据失败`) }); }, /** * 关闭模态框 */ closeModal: function() { DOM.studentModal.css("display", "none"); }, /** * 表单验证 * @returns {boolean} 验证结果(true=通过,false=不通过) */ validateForm: function() { let isValid = true; const stuname = DOM.stuname.val().trim(); const password = DOM.password.val().trim(); const grade = DOM.grade.val().trim(); const major = DOM.major.val().trim(); const phone = DOM.phone.val().trim(); // 姓名验证 if (!stuname) { $("#stunameError").show(); isValid = false; } else { $("#stunameError").hide(); } // 密码验证 if (!password) { $("#passwordError").show(); isValid = false; } else { $("#passwordError").hide(); } // 年级验证 if (!grade) { $("#gradeError").show(); isValid = false; } else { $("#gradeError").hide(); } // 专业验证 if (!major) { $("#majorError").show(); isValid = false; } else { $("#majorError").hide(); } // 电话验证(简单格式) const phoneReg = /^1[3-9]\d{9}$/; if (!phone || !phoneReg.test(phone)) { $("#phoneError").text("请输入有效手机号"); $("#phoneError").show(); isValid = false; } else { $("#phoneError").hide(); } return isValid; }, /** * 隐藏所有表单错误提示 */ hideAllErrors: function() { $("#stunameError, #passwordError, #gradeError, #majorError, #phoneError").hide(); }, /** * 提交表单(新增/编辑) */ submitForm: function() { Tool.log("开始提交表单"); // 表单验证 if (!this.validateForm()) { Tool.log("表单验证失败"); return; } // 构建提交数据 const studentData = { stuname: DOM.stuname.val().trim(), password: DOM.password.val().trim(), grade: DOM.grade.val().trim(), major: DOM.major.val().trim(), phone: DOM.phone.val().trim() }; // 编辑模式:添加ID const studentId = DOM.studentId.val().trim(); const isEdit = !!studentId; if (isEdit) { studentData[SystemConfig.ID_FIELD] = studentId; } // 发送请求 $.ajax({ url: `${SystemConfig.API_BASE_URL}/student`, type: isEdit ? "PUT" : "POST", contentType: "application/json", data: JSON.stringify(studentData), success: () => { const msg = isEdit ? "学生信息更新成功" : "新学生添加成功"; Tool.log(msg); Tool.showStatus(msg); this.closeModal(); // 关闭模态框 this.loadStudents(); // 重新加载列表 }, error: Tool.handleAjaxError(isEdit ? "更新学生失败" : "新增学生失败") }); }, /** * 删除学生 * @param {string} id - 学生ID */ deleteStudent: function(id) { if (!confirm("确定要删除这条学生记录吗?删除后不可恢复!")) { return; } if (!id || id === "未知") { Tool.showStatus("学生ID无效,删除失败", false); return; } Tool.log(`开始删除学生,ID:${id}`); $.ajax({ url: `${SystemConfig.API_BASE_URL}/student/${id}`, type: "DELETE", success: () => { const msg = `ID为${id}的学生已删除`; Tool.log(msg); Tool.showStatus(msg); this.loadStudents(); // 重新加载列表 }, error: Tool.handleAjaxError(`删除ID为${id}的学生失败`) }); } }; // 5. 页面加载完成后初始化 $(document).ready(() => { StudentService.init(); }); </script> </body> </html>页面不显示,数据库显示,代码怎么修改
09-30
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值