原生JS动态加载JSON至datalist及动态表单字段填充问题
问题解答
疑问解答
- 需求完全可行:你所说的“HTML变量”本质是全局作用域下的JavaScript变量,只要定义在全局(比如页面的
<script>标签最外层),DOM结构变更后它的作用域不受影响,随时可以被调用使用。
现有代码的问题
- 重复定义
types_json变量:先通过document.createElement创建了一个无用的DOM元素,后续又将其覆盖为后端返回的JSON数组,前序定义完全冗余。 populate_datalist函数逻辑固化:函数内固定操作初始的dataList元素,无法适配动态创建的新datalist,需要改为接收目标datalist元素作为参数。- 初始input的
onFocus会重复填充:每次聚焦都会执行填充逻辑,导致datalist中出现大量重复选项,需要添加判断避免重复操作。 - 缺少动态添加字段组的核心逻辑:你提到需要点击按钮新增字段,但现有代码无对应按钮和实现代码。
- 元素ID重复:动态添加字段时会生成重复ID(如
datalisttype1),违反HTML中ID必须唯一的规则,需用递增序号区分。 - 下拉框
relevance_ent的name未使用数组形式:提交时只会获取最后一个选中值,需改为relevance_ent[]才能提交多条记录。
修正后的完整代码
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>?do=addnewstructure" enctype="multipart/form-data"> <!-- 初始字段组 --> <div class="field-group" data-index="1"> <div> <input list="datalistOptions_1" id="datalisttype_1" name="deftype_ent[]" placeholder="Type to search..." onFocus="populateDatalist('datalistOptions_1')"> <datalist id="datalistOptions_1"> <option value="first">First persistent option</option> </datalist> </div> <div> <label for="value_ent_1">Name</label> <input type="text" name="defvalue_ent[]" id="value_ent_1"> </div> <div> <label for="relevance_ent_1">Relevance</label> <select id="relevance_ent_1" name="relevance_ent[]"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> </select> </div> </div> <!-- 添加字段按钮 --> <button type="button" id="addFieldBtn">添加新记录</button> <button type="submit">提交所有记录</button> </form> <script> // 全局保存后端返回的JSON数据,避免重复请求 const typesJson = <?php echo json_encode($results_json); ?>; // 填充datalist的通用函数,接收目标datalist的ID function populateDatalist(datalistId) { const datalist = document.getElementById(datalistId); // 判断是否已经填充过,避免重复添加选项 if (datalist.dataset.populated === 'true') return; typesJson.forEach(item => { const option = document.createElement('option'); option.value = item.type_id; option.text = item.name; datalist.appendChild(option); }); // 标记已填充,防止重复执行 datalist.dataset.populated = 'true'; } // 动态添加字段组的逻辑 document.getElementById('addFieldBtn').addEventListener('click', function() { // 获取现有字段组的数量,生成新的索引 const fieldGroups = document.querySelectorAll('.field-group'); const newIndex = fieldGroups.length + 1; // 创建新的字段组容器 const newGroup = document.createElement('div'); newGroup.className = 'field-group'; newGroup.dataset.index = newIndex; // 拼接字段组的HTML内容 newGroup.innerHTML = ` <div> <input list="datalistOptions_${newIndex}" id="datalisttype_${newIndex}" name="deftype_ent[]" placeholder="Type to search..." onFocus="populateDatalist('datalistOptions_${newIndex}')"> <datalist id="datalistOptions_${newIndex}"> <option value="first">First persistent option</option> </datalist> </div> <div> <label for="value_ent_${newIndex}">Name</label> <input type="text" name="defvalue_ent[]" id="value_ent_${newIndex}"> </div> <div> <label for="relevance_ent_${newIndex}">Relevance</label> <select id="relevance_ent_${newIndex}" name="relevance_ent[]"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> </select> </div> `; // 将新字段组添加到表单中 this.before(newGroup); }); </script>
内容的提问来源于stack exchange,提问作者M Wasabi Z
相关产品推荐
相关产品推荐

