You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Thymeleaf实现可点击展开详情的动态表格(无jQuery)

实现可点击展开/收起的动态表格行(Thymeleaf + JS + CSS)

当然可行!咱们完全可以用你指定的技术栈(Thymeleaf、JS、HTML、CSS、Java)实现这个点击展开/收起详情的功能。核心思路是给每个数据行添加点击事件,切换对应详情行的显示状态,下面是具体的实现步骤和完整代码:

1. 调整Thymeleaf表格结构

我们需要给每个数据行添加唯一标识,同时在每一行下方插入一个跨列的隐藏详情行,用来渲染该行对应的动态详情数据。假设你的Projectphase对象有一个getDetails()方法返回详情列表(比如子任务、明细数据等),代码调整如下:

<body>
  <style>
    .data-row {
      cursor: pointer;
      transition: background-color 0.2s;
    }
    .data-row:hover {
      background-color: #f5f5f5;
    }
    .data-row.highlighted {
      background-color: #e8f4f8;
    }
    .details-row {
      display: none;
      background-color: #fafafa;
    }
    .details-row.active {
      display: table-row;
    }
    .details-content {
      padding: 15px;
    }
    .detail-item {
      margin: 5px 0;
      padding: 8px;
      border-bottom: 1px solid #eee;
    }
  </style>

  <table border="1" cellpadding="8" cellspacing="0">
    <tr>
      <th>Phasen Name</th>
      <th>PC</th>
      <th>AC</th>
      <th>EV</th>
    </tr>
    <!-- 数据行 -->
    <tr th:each="Projectphase, iterStat : ${evaPhasen}" class="data-row" data-id="phase-${iterStat.index}">
      <td th:text="${Projectphase.phasenname}"></td>
      <td th:text="${Projectphase.plannedValue}"></td>
      <td th:text="${Projectphase.actualCost}"></td>
      <td th:text="${Projectphase.earnedValue}"></td>
    </tr>
    <!-- 详情行 -->
    <tr th:each="Projectphase, iterStat : ${evaPhasen}" class="details-row" id="details-phase-${iterStat.index}">
      <td colspan="4" class="details-content">
        <h4>详情 - <span th:text="${Projectphase.phasenname}"></span></h4>
        <div th:if="${not #lists.isEmpty(Projectphase.details)}">
          <div th:each="detail : ${Projectphase.details}" class="detail-item">
            <span th:text="${detail.name}"></span>: <span th:text="${detail.value}"></span>
          </div>
        </div>
        <div th:if="${#lists.isEmpty(Projectphase.details)}">
          <em>无详情数据</em>
        </div>
      </td>
    </tr>
  </table>

  <script>
    // 获取所有数据行
    const dataRows = document.querySelectorAll('.data-row');
    dataRows.forEach(row => {
      row.addEventListener('click', function() {
        // 获取当前行的标识ID
        const phaseId = this.getAttribute('data-id');
        // 找到对应的详情行
        const detailsRow = document.getElementById(`details-${phaseId}`);
        // 切换显示状态
        detailsRow.classList.toggle('active');
        // 给点击的行添加/移除高亮样式
        this.classList.toggle('highlighted');
      });
    });
  </script>
</body>

2. 各部分代码说明

  • Thymeleaf部分
    • 使用iterStat.index给每个数据行和详情行生成唯一标识,确保二者一一对应;
    • 详情行用colspan="4"跨所有列,保证表格布局整齐;
    • 通过th:if判断是否存在详情数据,动态显示对应内容。
  • CSS部分
    • 给数据行添加鼠标悬停效果和指针样式,提升交互体验;
    • 默认隐藏详情行,通过active类控制显示状态;
    • 给详情内容添加内边距和分隔线,优化视觉层次感。
  • JavaScript部分
    • 监听所有数据行的点击事件;
    • 通过data-id属性关联对应的详情行,使用classList.toggle()一键切换显示/隐藏状态;
    • 可选的高亮样式,让用户更清晰地识别当前点击的行。

3. Java后端配合

确保你的Projectphase实体类包含详情数据的属性和getter方法,示例如下:

public class Projectphase {
    private String phasenname;
    private Double plannedValue;
    private Double actualCost;
    private Double earnedValue;
    private List<Detail> details; // 存储该行的详情数据

    // 省略其他属性的getter/setter
    public List<Detail> getDetails() {
        return details;
    }

    public void setDetails(List<Detail> details) {
        this.details = details;
    }

    // 内部类定义详情数据结构
    public static class Detail {
        private String name;
        private String value;

        // getter/setter方法
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        public String getValue() { return value; }
        public void setValue(String value) { this.value = value; }
    }
}

在后端控制器中,给每个Projectphase对象填充好详情数据后,再将evaPhasen列表传递到前端即可。

这样就能完美实现点击数据行展开对应详情、再次点击收起的功能啦!

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

火山引擎 最新活动