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

如何在可拖拽重排仪表板中隔离各Panel的FormData

解决仪表板面板FormData数据隔离问题

1. 给每个面板添加唯一标识与独立隐藏输入框

每个面板创建时生成唯一ID(自增数字或UUID均可),在面板内部嵌入专属隐藏输入框,用于存储当前面板的FormData。输入框的name和id需关联面板ID,保证唯一性。

JSP动态生成示例:

<c:forEach var="panel" items="${panels}" varStatus="status">
  <div class="dashboard-panel" data-panel-id="${panel.id}">
    <div class="panel-content">
      <!-- 面板配置控件(下拉框、多选框等) -->
    </div>
    <!-- 隐藏输入框存储当前面板的FormData -->
    <input type="hidden" 
           name="panel-form-data-${panel.id}" 
           id="panel-form-data-${panel.id}" 
           value="${panel.formDataJson}" />
  </div>
</c:forEach>

2. 新增面板时初始化独立的FormData

点击新增按钮时,生成新面板ID并初始化与已有面板不同的默认FormData,写入对应隐藏输入框,避免数据重复。

JavaScript示例:

let panelCounter = document.querySelectorAll('.dashboard-panel').length;

document.getElementById('add-panel-btn').addEventListener('click', function() {
  panelCounter++;
  const newPanelId = `panel-${panelCounter}`;
  // 初始化新面板的独立FormData,与已有面板区分
  const defaultFormData = {
    type: `${panelCounter}`,
    panellogsource: "19",
    fieldSelected: [],
    timeWindow: "Last 15 Minutes"
    // 根据面板类型追加对应字段,如type=2时添加aggregateType
  };
  const formDataJson = JSON.stringify(defaultFormData);

  // 构建新面板DOM
  const newPanel = document.createElement('div');
  newPanel.className = 'dashboard-panel';
  newPanel.dataset.panelId = newPanelId;
  newPanel.innerHTML = `
    <div class="panel-content">
      <select name="chartType" class="chart-type-select">...</select>
      <!-- 其他配置控件 -->
    </div>
    <input type="hidden" 
           name="panel-form-data-${newPanelId}" 
           id="panel-form-data-${newPanelId}" 
           value="${formDataJson}" />
  `;

  document.getElementById('dashboard-container').appendChild(newPanel);
  // 绑定配置控件的变更事件
  bindPanelFormEvents(newPanelId);
});

3. 配置控件变更时同步更新对应面板的FormData

给每个面板的配置控件绑定变更事件,修改时实时更新对应隐藏输入框中的FormData,保证数据一致性。

JavaScript绑定函数示例:

function bindPanelFormEvents(panelId) {
  const panel = document.querySelector(`[data-panel-id="${panelId}"]`);
  const formDataInput = panel.querySelector(`#panel-form-data-${panelId}`);
  const controls = panel.querySelectorAll('select, input[type="text"], input[type="checkbox"]');

  controls.forEach(control => {
    control.addEventListener('change', function() {
      let formData = JSON.parse(formDataInput.value);
      const controlName = this.name;

      // 处理多选框特殊情况
      if (this.type === 'checkbox') {
        formData[controlName] = formData[controlName] || [];
        if (this.checked) {
          formData[controlName].push(this.value);
        } else {
          formData[controlName] = formData[controlName].filter(item => item !== this.value);
        }
      } else {
        formData[controlName] = this.value;
      }

      // 重新序列化写入隐藏输入框
      formDataInput.value = JSON.stringify(formData);
    });
  });
}

4. 保存时遍历获取所有面板的独立FormData

点击保存按钮时,遍历所有面板的隐藏输入框,收集每个面板的FormData,统一提交或处理。

JavaScript保存逻辑示例:

document.getElementById('save-dashboard-btn').addEventListener('click', function() {
  const allPanelData = [];
  const formDataInputs = document.querySelectorAll('input[name^="panel-form-data-"]');

  formDataInputs.forEach(input => {
    const panelId = input.name.replace('panel-form-data-', '');
    allPanelData.push({
      panelId: panelId,
      formData: JSON.parse(input.value)
    });
  });

  // 提交到后台或进行后续处理
  console.log('所有面板数据:', allPanelData);
  // fetch('/save-dashboard', {
  //   method: 'POST',
  //   headers: { 'Content-Type': 'application/json' },
  //   body: JSON.stringify(allPanelData)
  // });
});

5. 编辑面板时读取对应FormData填充控件

点击面板编辑按钮时,根据面板ID读取对应隐藏输入框的FormData,将数据填充到配置控件中。

JavaScript编辑逻辑示例:

document.addEventListener('click', function(e) {
  if (e.target.classList.contains('edit-panel-btn')) {
    const panel = e.target.closest('.dashboard-panel');
    const panelId = panel.dataset.panelId;
    const formDataInput = panel.querySelector(`#panel-form-data-${panelId}`);
    const formData = JSON.parse(formDataInput.value);

    // 填充配置控件
    panel.querySelectorAll('select, input').forEach(control => {
      const controlName = control.name;
      if (formData[controlName] === undefined) return;

      if (control.type === 'checkbox') {
        control.checked = formData[controlName].includes(control.value);
      } else {
        control.value = formData[controlName];
      }
    });
  }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 05:07:03