Knockout中首个表单submit正常其余失效问题求助
排查多视图PDF提交失败的问题
我之前也遇到过类似的表单提交不一致的问题,结合你提供的代码,大概率是重复的表单ID/名称或者表单查找逻辑不准确导致的,咱们来一步步解决:
核心问题分析
重复的ID和Name属性
你在foreach循环里给所有表单用了固定的ID(比如ateranstallpdf)和Name(比如avanmalan),这会导致DOM中存在多个完全相同ID/Name的表单元素。当你用document.forms[name]或者$(formid)查找表单时,浏览器只会返回第一个匹配的元素,这就解释了为什么只有第一个视图的表单能正常提交,后面的都失效了。Knockout渲染的异步性
你提到加了setTimeout后提交成功,这说明在点击事件触发时,可能Knockout还没完成当前项的DOM渲染,或者相关数据还没同步到DOM中,导致表单元素的状态不符合预期。
具体解决方案
方案1:给每个表单生成唯一标识
在foreach循环中,利用当前项的唯一属性(比如每个消息的id)来动态设置表单的ID和Name,确保每个表单都是唯一的:
<!-- 修改无法工作的视图中的表单 --> <form action="/createPDF.html" method="POST" data-bind="attr: {id: 'ateranstallpdf-' + id, name: 'avanmalan-' + id}" target="_blank"> <span onclick=""></span> <a href="javascript: void(0);" data-bind="click: function(){ $root.rem.print($data, $element); }" id="print-tgl">Skriv ut</a> </form>
然后修改对应的打印方法,传入当前表单的ID:
rem.print = function(data, element){ var formId = $(element).closest('form').attr('id'); var formName = $(element).closest('form').attr('name'); mainPdfPrint(formId, data, formName); }
方案2:直接通过事件上下文获取表单(更可靠)
避免依赖ID/Name查找表单,而是通过点击事件的目标元素直接找到父表单,这样完全不会有重复标识的问题:
首先修改mainPdfPrint方法,直接接收jQuery表单对象:
function mainPdfPrint($form, datasource, stringified) { var url = $form.attr("action"); var data = stringified ? datasource : JSON.stringify(datasource); var formName = $form.attr('name'); // 移除旧的隐藏输入 $form.find("input:hidden").remove(); // 添加新的隐藏输入 $form.append($("<input>", { "value": data, "name": formName, "type": "hidden" })); IK.global.logAnalytics(url); // 直接提交当前表单 $form[0].submit(); }
然后修改Knockout的点击绑定,传入事件对象:
<a href="javascript: void(0);" data-bind="click: function(data, event){ $root.rem.print(data, event); }" id="print-tgl">Skriv ut</a>
最后更新打印方法:
rem.print = function(data, event){ // 通过事件目标找到父表单 var $form = $(event.target).closest('form'); mainPdfPrint($form, data); }
方案3:解决Knockout异步渲染问题
如果是因为DOM还没完全更新导致的,除了固定延迟,还可以用setTimeout(0)(比固定延迟更优雅,利用浏览器事件循环确保DOM已更新):
self.print = function (data, event) { setTimeout(function () { var $form = $(event.target).closest('form'); $form[0].submit(); }, 0); }
验证建议
- 打开浏览器开发者工具(F12),查看Elements面板,确认
foreach生成的表单是否有重复的ID/Name。 - 在
mainPdfPrint方法里加console.log($form),确认每次提交的是正确的表单元素。
内容的提问来源于stack exchange,提问作者Fredrik Fahlman
相关产品推荐
相关产品推荐

