formBuilder基于已有数据构建表单时报getData is not a function错误
formBuilder 报错
fb.actions.getData is not a function 修复 报错表现
fb.actions.getData is not a function
触发时机:基于已有数据初始化多页表单构建器,完成表单修改后点击保存按钮时抛出。
问题代码
const result = <?php echo $questiondata->json_question;?>; let length = result.length; var stepLen = length; var res = result; for (let i = 1; i <= stepLen; i++) { var tabId = "step-" + i; const $newPageTemplate = $(document.getElementById("new-page")); const $newPage = $newPageTemplate.clone().attr("id", tabId).addClass("fb-editor"); const $newTab = $('#add-page-tab').clone().removeAttr("id"); const $tabLink = $("a", $newTab).attr("href", "#" + tabId).text("Step " + i); $newPage.insertBefore($newPageTemplate); $newTab.insertBefore('#add-page-tab'); $fbPages.tabs("refresh"); $fbPages.tabs("option", "active", 0); fbInstances.push($newPage.formBuilder()); $(tabId).formBuilder().promise.then(function(fb) { let formadata = res[i - 1]; fb.actions.setData(formadata); }); } //--------json form data update------------- $(document.getElementById("save-all")).click(function() { let allData = fbInstances.map((fb) => { console.log(fb.actions.getData()); // 报错行 return fb.actions.getData(); // 报错行 }); saveFormData(allData); });
问题根因
- 实例存储错误:
$newPage.formBuilder()返回的是插件初始化阶段的包装对象,不是加载完成的完整表单构建器实例,这个阶段实例上没有挂载完整的actions方法,直接存到fbInstances里调用方法自然会报错。完整可操作的实例只会在.promise的回调中返回。 - 重复初始化:循环中对同一个DOM元素调用了两次
.formBuilder():第一次是push到实例数组时,第二次是取promise填充初始数据时,相当于同一个页面初始化了两个独立的formBuilder实例,存到数组里的实例和实际页面渲染、用户操作的实例完全不是同一个引用。 - 选择器错误:
$(tabId)写法无效,tabId是step-x格式的字符串,作为id选择器需要加#前缀,该问题会被前面的重复初始化问题覆盖,不会第一时间触发。
修复方案
- 对每个分页DOM只初始化一次formBuilder,禁止重复调用初始化方法
- 等待实例加载完成(promise resolve)后,把返回的完整实例存入
fbInstances数组,不要存储初始化阶段的包装对象 - 初始数据填充逻辑直接在初始化promise回调中完成,不需要重新查找DOM元素
修复后代码
const result = <?php echo $questiondata->json_question;?>; const stepLen = result.length; const res = result; const fbInstances = []; for (let i = 1; i <= stepLen; i++) { const tabId = "step-" + i; const $newPageTemplate = $(document.getElementById("new-page")); const $newPage = $newPageTemplate.clone().attr("id", tabId).addClass("fb-editor"); const $newTab = $('#add-page-tab').clone().removeAttr("id"); // 补上原代码定义了未执行的tab链接更新逻辑 $newTab.find("a").attr("href", "#" + tabId).text("Step " + i); $newPage.insertBefore($newPageTemplate); $newTab.insertBefore('#add-page-tab'); $fbPages.tabs("refresh"); $fbPages.tabs("option", "active", 0); // 单实例初始化,不重复调用formBuilder const fbInit = $newPage.formBuilder(); fbInit.promise.then(function(fb) { // 填充初始表单数据 const formData = res[i - 1]; fb.actions.setData(formData); // 仅将加载完成的完整实例存入数组 fbInstances.push(fb); }); } // 全量保存表单逻辑 $(document.getElementById("save-all")).click(function() { const allData = fbInstances.map((fb) => { // 此时fb为完整实例,可正常调用getData方法 return fb.actions.getData(); }); saveFormData(allData); });
注意:如果你使用的formBuilder版本较新,
getData/setData可能直接挂载在实例对象上,调用方式为fb.getData()/fb.setData(),如果修复后仍提示方法不存在,去掉.actions层级直接调用即可。
内容的提问来源于stack exchange,提问作者Amitabh
相关产品推荐
相关产品推荐

