修改EJS标签实现点击添加表单输入框的问题求助
解决动态添加食谱步骤/配料输入框的问题
先看你代码里的核心问题:你创建的tempDiv是空的,就算插入DOM也看不到内容;另外原EJS代码里有重复的id属性(比如instructionGroup和instructions),这会导致DOM选择器冲突,后续操作容易出问题。
第一步:修正EJS视图代码(解决重复ID问题)
把重复的id改成class,同时给整个步骤区域加一个容器,方便后续插入新元素:
<div class="mb-3" id="instructionsContainer"> <label class="form-label" for="instructions" id="labelInstructions">instructions</label> <% for(let i = 0; i<3; i++){ %> <div class="input-group instruction-group mb-2"> <div class="input-group-prepend"> <span class="input-group-text">Step <%= i+1 %> </span> </div> <textarea class="form-control" aria-label="<%=`Instructions-Step-${i +1}`%>" name="<%=`recipe[instructions][${i}][body]` %>" id="<%=`instructions-step-${i+1}`%>"></textarea> </div> <div class="valid-feedback">Looks good!</div> <% } %> <button onclick="addInstruction()">+ Add Step</button> </div>
第二步:重写JS函数(生成带内容的输入框)
需要创建完整的输入组结构,而不是空div,同时动态计算步骤编号和name属性,保证后端能正确接收数组格式的数据:
function addInstruction() { // 获取当前已有的步骤数量,计算新步骤的编号和下标 const existingGroups = document.querySelectorAll('.instruction-group'); const newStepIndex = existingGroups.length; const newStepNumber = newStepIndex + 1; // 创建新的步骤输入组容器 const newGroup = document.createElement('div'); newGroup.className = 'input-group instruction-group mb-2'; // 填充输入组的HTML结构 newGroup.innerHTML = ` <div class="input-group-prepend"> <span class="input-group-text">Step ${newStepNumber}</span> </div> <textarea class="form-control" aria-label="Instructions-Step-${newStepNumber}" name="recipe[instructions][${newStepIndex}][body]" id="instructions-step-${newStepNumber}"></textarea> `; // 把新元素插入到按钮前面,保持布局顺序 const container = document.getElementById('instructionsContainer'); container.insertBefore(newGroup, container.querySelector('button')); }
关键说明
- 空div问题:之前创建的
tempDiv没有任何内容,所以插入后看不到,现在直接生成带input-group结构的完整元素。 - 重复ID问题:每个步骤组用
class="instruction-group"代替重复的id,避免DOM选择器冲突;每个textarea的id也改成唯一的instructions-step-${编号}。 - 动态name属性:新步骤的
name属性用newStepIndex作为数组下标,后端可以直接按数组接收所有步骤内容。
配料输入框的复用思路
配料输入框的实现逻辑完全一样,只需要把类名、name属性前缀改成配料相关的即可,比如:
- 类名改成
ingredient-group - name属性改成
recipe[ingredients][${index}][name](如果需要区分配料名称和数量,可以拆成两个输入框)
关于修改EJS循环次数的思路
这种方法需要前端触发请求让后端重新渲染页面,体验远不如前端动态添加便捷——因为只是表单元素的增加,不需要后端参与,前端动态生成是最优解。
内容的提问来源于stack exchange,提问作者rubenaguirre
相关产品推荐
相关产品推荐

