动态添加的Select2组件无法触发jQuery Validation验证问题
购物车表单验证失效问题
我正在开发一个支持用户添加多商品到购物车的表单,要求所有必填字段(商品选择、数量)不能为空。目前用了Select2插件、jQuery Validator和jQuery实现,但即使配置了验证规则,字段为空时表单仍能提交。
我给字段加了统一类名,希望对所有现有及新增行的商品选择框、数量输入框应用必填验证,阻止未填时提交表单。
<form name='CartForm' id='CartForm' method='post'> <table class="table table-condensed table-bordered no-padding" id="myTable"> <thead> <tr role="row" class="bg-blue"> <th class="tcenter" style="vertical-align:top; width:30%">Item #, UPC or Item Name</th> <th class="tcenter" style="vertical-align:top; width:7%">Quantity</th> <th class="tcenter" style="vertical-align:top; width:9%">PO Number</th> </tr> </thead> <tbody> <tr> <td class="tleft"> <select name="view_by_item[]" data-id="1" id="view_by_item1" class="form-control view_by_item" style='width: 100%'></select> </td> <td class="tcenter"> <input type="number" name="qty[]" id="qty1" class="qty form-control" style="text-align:right"> </td> <td class="tcenter"> <input type="text" name="ponum[]" class="ponum form-control" placeholder="Optional"> </td> </tr> <tr> <td class="tleft"> <select name="view_by_item[]" data-id="2" id="view_by_item2" class="form-control view_by_item" style='width: 100%'></select> </td> <td class="tcenter"> <input type="number" name="qty[]" id="qty2" class="qty form-control" style="text-align:right"> </td> <td class="tcenter"> <input type="text" name="ponum[]" class="ponum form-control" placeholder="Optional"> </td> </tr> </tbody> </table> <button type="button" class="btn btn-secondary plusbutton"> Add Item</button> <button class="btn btn-primary btn-flat" id="Place_order_btn">Place Order</button> </form>
function formatRepo (repo) { if (repo.loading) { return repo.text; } var $container = $( "<div class='select2-result-repository clearfix'>" + "<div class='select2-result-repository__meta'>" + "<div class='select2-result-repository__title'></div>" + "</div>" + "</div>" + "</div>" ); $container.find(".select2-result-repository__title").text(repo.full_name); return $container; } function formatRepoSelection (repo) { return repo.full_name || repo.text; } function attachItems(item_elt){ item_elt = typeof(item_elt) == 'undefined'?'.view_by_item':item_elt; $(document).find(item_elt).select2({ ajax: { url: "https://api.github.com/search/repositories", dataType: 'json', delay: 250, data: function (params) { return { q: params.term, // search term page: params.page }; }, processResults: function (data, params) { params.page = params.page || 1; return { results: data.items, pagination: { more: (params.page * 30) < data.total_count } }; }, cache: true }, placeholder: 'Search for a repository', minimumInputLength: 3, templateResult: formatRepo, templateSelection: formatRepoSelection }); } var rowCount = 2; $(document).on('click', '.plusbutton',function(e){ e.preventDefault(); rowCount++; var newRow = '<tr>'; newRow += '<td class="tleft"><select name="view_by_item[]" data-id="'+rowCount+'" id="view_by_item'+rowCount+'" class="form-control view_by_item" style="width: 100%"></select></td>'; newRow += '<td class="tcenter"><input type="number" name="qty[]" id="qty'+rowCount+'" class="qty form-control" style="text-align:right" /></td>'; newRow += '<td class="tcenter"><input type="text" name="ponum[]" class="ponum form-control" placeholder="Optional"/></td>'; $("#myTable tbody").append(newRow); attachItems('#view_by_item'+rowCount); }); attachItems(); $('#CartForm').validate({ ignore: [], rules:{ '.view_by_item':{required: true}, '.qty': {required: true} }, submitHandler: function() { alert('No errors'); return false; } });
问题分析与修复方案
核心问题
jQuery Validator的rules配置不支持直接用类名作为键,必须针对表单元素的name属性,或者通过rules('add')方法动态绑定规则。另外,Select2会隐藏原生select元素,需确保Validator不忽略隐藏元素,同时要处理动态新增行的验证绑定。
修复步骤
- 改用
rules('add')方法遍历元素添加验证规则,替代初始化时的类名配置 - 给Select2绑定
change事件,选择后触发验证状态更新 - 新增行后,立即为新元素绑定验证规则
修改后的完整JavaScript代码
function formatRepo (repo) { if (repo.loading) { return repo.text; } var $container = $( "<div class='select2-result-repository clearfix'>" + "<div class='select2-result-repository__meta'>" + "<div class='select2-result-repository__title'></div>" + "</div>" + "</div>" + "</div>" ); $container.find(".select2-result-repository__title").text(repo.full_name); return $container; } function formatRepoSelection (repo) { return repo.full_name || repo.text; } function attachItems(item_elt){ item_elt = typeof(item_elt) == 'undefined'?'.view_by_item':item_elt; $(document).find(item_elt).select2({ ajax: { url: "https://api.github.com/search/repositories", dataType: 'json', delay: 250, data: function (params) { return { q: params.term, page: params.page }; }, processResults: function (data, params) { params.page = params.page || 1; return { results: data.items, pagination: { more: (params.page * 30) < data.total_count } }; }, cache: true }, placeholder: 'Search for a repository', minimumInputLength: 3, templateResult: formatRepo, templateSelection: formatRepoSelection }).on('change', function() { // Select2选择变化时触发验证 $(this).valid(); }); } // 为元素添加验证规则 function addValidationRules() { // 商品选择框必填规则 $('.view_by_item').each(function() { $(this).rules('add', { required: true, messages: { required: '请选择商品' } }); }); // 数量输入框必填规则 $('.qty').each(function() { $(this).rules('add', { required: true, messages: { required: '请输入数量' } }); }); } var rowCount = 2; $(document).on('click', '.plusbutton',function(e){ e.preventDefault(); rowCount++; var newRow = '<tr>'; newRow += '<td class="tleft"><select name="view_by_item[]" data-id="'+rowCount+'" id="view_by_item'+rowCount+'" class="form-control view_by_item" style="width: 100%"></select></td>'; newRow += '<td class="tcenter"><input type="number" name="qty[]" id="qty'+rowCount+'" class="qty form-control" style="text-align:right" /></td>'; newRow += '<td class="tcenter"><input type="text" name="ponum[]" class="ponum form-control" placeholder="Optional"/></td>'; $("#myTable tbody").append(newRow); // 初始化新的Select2 attachItems('#view_by_item'+rowCount); // 为新元素绑定验证规则 addValidationRules(); }); // 初始化表单验证 $('#CartForm').validate({ ignore: [], // 不忽略隐藏元素,适配Select2 submitHandler: function(form) { alert('验证通过,可提交表单'); // 此处可添加实际提交逻辑,如form.submit(); return false; } }); // 初始化Select2和验证规则 attachItems(); addValidationRules();
关键修改说明
- 验证规则绑定:用
rules('add')替代初始化时的类名配置,解决Validator无法识别类名规则的问题 - Select2联动验证:通过
change事件触发valid(),确保选择操作能同步验证状态 - 动态行处理:新增行后立即调用
addValidationRules(),保证新元素也能被纳入验证范围
内容的提问来源于stack exchange,提问作者Rahul Roy
相关产品推荐
相关产品推荐

