Layui 动态添加/删除表单行需手动操作DOM并调用layui.form.render()重新绑定,确保新控件含正确class和lay-verify属性,删除时清理name属性或使用索引命名,提交前用layui.form.val()获取有效数据。
如何用 Layui 动态添加/删除表单行(不依赖 table 模块)
直接结论:layui 本身没有内置的“动态表单行”组件,得靠手动操作 dom + layui.form.render() 重新绑定。关键不是加几行,而是新加的 input、select 等控件必须被 form 模块识别,否则无法校验、取值、渲染样式。
常见错误是只 append HTML,忘了调用 form.render(),结果新行看着像输入框,点不了、选不了、提交时拿不到值。
- 新增行必须包含正确的 Layui class(如
layui-input、layui-select),否则样式错乱 - 如果用了
lay-verify,新行控件也要带上,且验证规则需与原有字段一致 - 删除行时,别只 remove DOM,要同步清理可能存在的事件监听(比如你给每行加了“删除按钮 click”)
添加一行时,怎么让新 input/select 正常工作
核心动作就两步:插入 HTML + 主动触发渲染。不能等用户操作完再 render,得在 append 后立刻做。
示例(假设容器 id 是 dynamic-form):
const newRow = `
<div class="layui-form-item">
<label class="layui-form-label">姓名</label>
<div class="layui-input-block">
<input type="text" name="name[]" lay-verify="required" placeholder="请输入姓名" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">性别</label>
<div class="layui-input-block">
<select name="gender[]" lay-filter="gender" class="layui-select">
<option value="">请选择</option>
<option value="1">男</option>
<option value="2">女</option>
</select>
</div>
</div>
`;
document.getElementById('dynamic-form').insertAdjacentHTML('beforeend', newRow);
layui.form.render('select'); // 单独渲染 select
layui.form.render('checkbox'); // 如果有 checkbox 也得单独 render
layui.form.render(); // 兜底:重绘所有 form 元素(包括 input、textarea 的验证和样式)
注意:form.render() 不带参数会处理全部;但如果有大量动态行,建议按类型分批 render,避免性能抖动。
删除某一行时,为什么 layui.form.verify() 还校验已删字段
因为 layui.form.verify() 是按 name 属性匹配的,哪怕 DOM 已删,只要页面里还存在同名 input[name="xxx"](比如你删得不干净、或用了 clone 而没清 name),验证就会触发。
安全做法是:删除前先移除该行所有 input 的 name 属性,或用 name="xxx[0]" 这类带索引的命名,并在提交前用 JS 动态收集有效行数据。
- 不要用
innerHTML = ''清空整个容器,会把还没删的行也干掉 - 删除按钮最好放在行内,用
btn.closest('.layui-form-item').remove()精准移除 - 如果用了 lay-submit 绑定提交,记得提交前用
layui.form.val('formFilter')获取当前实际表单值——它只会读取现存 DOM 中的字段
多行带日期/下拉联动时,怎么避免重复绑定事件
Layui 的 laydate 和 form.on('select(filter)') 默认只对初始 DOM 生效。动态添加的控件,必须手动初始化。
比如新增行里有日期控件:
// 新增后立即初始化
layui.laydate.render({
elem: '.layui-form-item:last-child .layui-input[name="date[]"]',
trigger: 'click'
});
// 下拉联动(比如省市区三级联动)
form.on('select(province)', function(data) {
// 注意:这里监听的是全局 select,不是某一行的 —— 所以 data.elem 是触发的那个 select
// 你要通过 data.elem.closest('.layui-form-item') 定位到所属行,再操作对应市/区下拉
});
容易踩的坑:同一个选择器多次调用 laydate.render(),会导致多个日历实例叠加;应在添加前先检查是否已初始化(比如加个 data-initialized="true" 标记)。
真实项目里,动态表单的复杂度不在“加减行”,而在状态同步:比如某行填了必填项,删掉后其他行的校验逻辑要不要重算?这类边界情况,Layui 不管,得自己用变量或 DOM class 控制。


















