You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Express、Mongoose在EJS模板实现联动动态下拉选框

联动下拉选框实现方案(Express+EJS+Mongoose)

问题说明

使用EJS、Express和Mongoose开发表单,需要实现第一个下拉选框驱动第二个选框动态更新的联动效果:

  • 后端已通过Mongoose查询得到optionOneList(对应Person: "queryOne")和optionTwoList(对应Person: "queryTwo")两个数组,并传递给EJS模板
  • 第一个选框包含queryOne、queryTwo选项,选择后第二个选框要渲染对应数组的Name字段作为选项

现有尝试的问题

  1. 将查询数组存入独立JS文件传入模板:无法把服务端EJS变量的值传递给客户端JS变量
  2. 在EJS的<script>标签中保存数组:页面加载后无法访问该变量(大概率是转义问题)
  3. 将数组设为EJS局部变量:仅服务端渲染时可用,客户端JS无法直接访问

解决方案建议

方案1:一次性加载所有数据,前端JS切换(适合数据量小的场景)

核心是把服务端传递的EJS变量转成客户端可访问的JS对象,通过监听第一个选框的change事件动态更新第二个选框的选项。

修改EJS模板代码

<!-- 第一个下拉选框 -->
<select id="firstSelection">
  <option selected>Default</option>
  <option value="queryOne">queryOne</option>
  <option value="queryTwo">queryTwo</option>
</select>

<!-- 第二个下拉选框 -->
<select id="secondSelection"></select>

<script>
// 用<%- %>避免JSON转义,将EJS变量转为客户端JS对象
const optionOneData = <%- JSON.stringify(optionOneList) %>;
const optionTwoData = <%- JSON.stringify(optionTwoList) %>;

const firstSelect = document.getElementById('firstSelection');
const secondSelect = document.getElementById('secondSelection');

// 监听第一个选框的变化事件
firstSelect.addEventListener('change', function() {
  const selectedVal = this.value;
  // 清空第二个选框现有选项
  secondSelect.innerHTML = '';

  let targetData = [];
  // 根据选择值匹配对应数据
  if (selectedVal === 'queryOne') {
    targetData = optionOneData;
  } else if (selectedVal === 'queryTwo') {
    targetData = optionTwoData;
  }

  // 生成新选项并插入第二个选框
  targetData.forEach(item => {
    const option = document.createElement('option');
    option.textContent = item.Name;
    secondSelect.appendChild(option);
  });
});
</script>

关键说明

  • 必须用<%- JSON.stringify(...) %>:<%= %>会对JSON字符串进行HTML转义,导致无法解析为JS对象;<%- %>会直接输出原始内容,保证JSON格式正确。
  • 前端JS通过DOM操作动态生成选项,无需重新渲染页面。

方案2:AJAX异步获取数据(适合数据量大或需要实时更新的场景)

如果不想一次性加载所有数据,可以在第一个选框变化时,通过AJAX请求后端接口获取对应数据,再渲染第二个选框。

1. 新增Express接口

app.get('/general/options', async (req, res) => {
  try {
    const person = req.query.person;
    // 根据前端传递的参数查询对应数据
    const options = await collectionOne.find({ "Person": person });
    res.json(options);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

2. 修改EJS模板前端代码

<!-- 第一个下拉选框 -->
<select id="firstSelection">
  <option selected>Default</option>
  <option value="queryOne">queryOne</option>
  <option value="queryTwo">queryTwo</option>
</select>

<!-- 第二个下拉选框 -->
<select id="secondSelection"></select>

<script>
const firstSelect = document.getElementById('firstSelection');
const secondSelect = document.getElementById('secondSelection');

firstSelect.addEventListener('change', async function() {
  const selectedVal = this.value;
  // 选择默认值时清空第二个选框
  if (!selectedVal || selectedVal === 'Default') {
    secondSelect.innerHTML = '';
    return;
  }

  try {
    // 发送请求获取对应数据
    const response = await fetch(`/general/options?person=${selectedVal}`);
    const options = await response.json();

    // 清空并生成新选项
    secondSelect.innerHTML = '';
    options.forEach(item => {
      const option = document.createElement('option');
      option.textContent = item.Name;
      secondSelect.appendChild(option);
    });
  } catch (err) {
    console.error('获取数据失败:', err);
  }
});
</script>

关键说明

  • 这种方案减少了初始页面加载的数据量,数据更实时(每次请求都是最新的数据库数据)。
  • 需要处理请求失败的异常情况,保证用户体验。

内容的提问来源于stack exchange,提问作者StunnedbymyStupidity

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 13:18:54