JavaScript中如何通过id属性实现动态表单必填字段的校验
动态表单必填校验实现方案
问题根源
你当前遇到的校验失效问题主要由3个原因导致:
- 初始静态表单的字段ID重复,没有加索引后缀,不符合DOM ID唯一的规范,导致按ID识别字段时出现冲突
- 你代码末尾那段
$("input").prop('required',true)逻辑错误,会把非必填的perkara2、perkara3也强制设为必填,同时干扰原生校验逻辑 - 原生表单校验本身支持
name[]格式的数组命名,不会因为name相同就跳过校验,你之前的失效本质是ID重复和错误的全局属性修改导致的
具体实现步骤
第一步:维护全局表单索引,修复初始表单ID
首先在页面JS全局位置声明索引变量,同时修改静态表单的字段ID,保证第一组表单ID唯一:
// 全局索引,初始静态表单用0,新增从1开始计数 let formIndex = 1;
静态表单的字段ID修改示例:
<!-- 原来的静态表单字段ID全部加_0后缀 --> <select class="form-control select2bs4" name="kod[]" id="kod_0" required> <input type="text" class="form-control form-control-sm" name="perkara1[]" id="perkara1_0" required> <input type="text" class="form-control form-control-sm" name="perkara2[]" id="perkara2_0" required="false"> <input type="text" class="form-control form-control-sm" name="perkara3[]" id="perkara3_0" required="false"> <input id="noruj_0" type="text" class="form-control form-control-sm" name="noruj[]" required> <input type="text" id="currency_0" class="form-control form-control-sm currency" name="jumlah[]" required>
第二步:修改新增表单的JS逻辑
修正新增逻辑,去掉错误的全局required设置,同时新增后重新初始化select2组件:
$('html, body').animate({scrollTop: '+=550px'}, 400); let i = formIndex; var html = ''; html += '<div class="callout callout-warning">'; html += '<div class="row"><div class="col-md-12"><h6><i class="far fa-file-alt"style="font-size:20px"></i><b style="padding-left:7px">Maklumat Bil</b><span class="float-sm-right" style="padding-left:5px"><button type="button" name="remove" class="btn btn-block btn-danger btn-sm right remove"><i class="fa fa-minus"></i> Padam Bil</button></span><span class="float-sm-right"><button type="button" name="add" class="btn btn-block btn-primary btn-sm right add"><i class="fa fa-plus"></i> Tambah Bil</button></span></h6><hr></div></div>'; html += '<div class="row"><div class="col-md-12"><div class="form-group"><label>Jabatan*</label><input type="hidden" name="jabatan[]" class="form-control" value="<?php echo $dept; ?>"><span class="form-control form-control-sm"><?php echo $jab; ?></span></div></div></div>'; html += '<div class="row"><div class="col-md-6">'; html += '<div class="form-group"><label>Kod*</label><select class="form-control select2bs4" name="kod[]" id ="kod_'+i+'" required><option value="" disabled="disabled" selected="selected">--Pilih Kod--</option><?php foreach($kod as $k):?><option value="<?php echo $k->kod;?>"><?php echo $k->kod;?> - <?php echo $k->keterangan;?></option><?php endforeach;?></select></div>'; html += '</div><div class="col-md-6">'; html += '<div class="form-group"><label>Perkara (Wajib isi ruangan pertama)*</label><input type="text" class="form-control form-control-sm" name="perkara1[]" id="perkara1_'+i+'" required><input type="text" class="form-control form-control-sm" name="perkara2[]" id="perkara2_'+i+'" style="margin-top:6px !important" ><input type="text" class="form-control form-control-sm" name="perkara3[]" id="perkara3_'+i+'" style="margin-top:6px !important" ></div>'; html += '</div></div>'; html += '<div class="row"><div class="col-md-6">'; html += '<div class="form-group"><label>No. Rujukan*</label><input id="noruj_'+i+'" type="text" class="form-control form-control-sm" name="noruj[]" required></div>'; html += '</div><div class="col-md-6">'; html += '<div class="form-group"><label>Jumlah (RM)*</label><input type="text" id="currency_'+i+'" class="form-control form-control-sm currency" name="jumlah[]" required></div>'; html += '</div><span>*Ruangan wajib diisi</span></div>'; html += '</div>'; $('#item').append(html); // 新增后初始化新增区块的select2组件 $('#kod_'+i).select2bs4(); // 索引自增,下次新增用新的索引 formIndex++;
第三步:自定义按ID/区块遍历的校验逻辑(可选)
如果你不想用原生表单校验,要自己实现校验逻辑,可以用以下方式按区块遍历,不需要依赖name属性,也可以按ID逐个校验:
// 表单提交前触发校验 $('form').on('submit', function(e) { let isValid = true; // 遍历每个表单区块 $('.callout.callout-warning').each(function(blockIndex) { // 查找当前区块内的所有必填字段 $(this).find('[required]').each(function() { let fieldId = $(this).attr('id'); let fieldVal = $(this).val().trim(); // 校验非空 if (fieldVal === '') { isValid = false; // 可以自定义提示样式,比如给字段加红色边框 $(this).addClass('is-invalid'); console.log('必填字段为空,ID:' + fieldId); } else { $(this).removeClass('is-invalid'); } }); }); // 校验不通过阻止提交 if (!isValid) { e.preventDefault(); alert('请填写所有必填字段'); return false; } });
补充说明
- 原生表单校验本身支持
name[]格式的字段,只要字段正确设置了required属性,提交时会自动校验所有同name的必填项,不需要额外修改 - 所有字段ID必须唯一,否则不管是DOM操作还是JS获取元素都会出现不可预期的错误
- 删除区块的时候不需要调整索引,只要保证每个字段ID不重复即可,不影响后端接收数组格式的参数
内容的提问来源于stack exchange,提问作者Nirah
相关产品推荐
相关产品推荐

