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

AngularJS实现三列表格rowspan功能遇问题,求解决方案

搞定三级分类表格的rowspan合并问题

嘿,我明白你现在的困扰——两列的合并没问题,但扩展到三列(分类、科目、课程)就乱套了。咱们一步步来解决这个问题:

先说说你原代码的核心问题

  • HTML结构不合法:<tbody>的直接子元素必须是<tr>,你之前在tbody里直接放<td>,浏览器会自动修正结构,导致渲染错乱。
  • 嵌套循环的写法错误:Angular里不能直接在<tr>里嵌套<tr>,得用ng-repeat-start和ng-repeat-end来处理跨多行的重复逻辑。
  • rowspan计算错误:三列场景下,分类的rowspan应该是该分类下所有课程的总行数(没课程的科目算1行),而不是科目数+1;科目rowspan是对应课程的数量(至少1行)。
  • 数据格式不一致:你的示例数据里有的courseList是JSON字符串(比如"[{\"name\":\"-\",\"curcount\":0}]"),有的是数组;课程名称字段有的是name有的是coursename,这些都会导致渲染异常。

修正后的完整实现

第一步:预处理数据(在控制器里)

先把数据格式统一,避免渲染时出问题:

// 预处理组织数据,修正格式问题
angular.forEach($scope.organization, function(category) {
  // 处理subjectList是字符串的情况
  if (typeof category.subjectList === 'string') {
    try {
      category.subjectList = JSON.parse(category.subjectList);
    } catch(e) {
      category.subjectList = [];
    }
  }
  angular.forEach(category.subjectList, function(subject) {
    // 处理courseList是字符串的情况
    if (typeof subject.courseList === 'string') {
      try {
        subject.courseList = JSON.parse(subject.courseList);
      } catch(e) {
        subject.courseList = [];
      }
    }
    // 统一课程名称字段为coursename
    angular.forEach(subject.courseList, function(course) {
      course.coursename = course.coursename || course.name;
    });
  });
});

// 计算分类需要合并的行数
$scope.getCategoryRowspan = function(category) {
  let totalRows = 0;
  angular.forEach(category.subjectList, function(subject) {
    const courseCount = subject.courseList?.length || 0;
    totalRows += courseCount > 0 ? courseCount : 1;
  });
  return totalRows;
};

// 计算科目需要合并的行数
$scope.getSubjectRowspan = function(subject) {
  const courseCount = subject.courseList?.length || 0;
  return courseCount > 0 ? courseCount : 1;
};

第二步:修正表格HTML

<table class="curvetable5" style="width:99%">
  <thead>
    <tr>
      <th width="30%">Category</th>
      <th width="30%">Subject</th>
      <th width="40%">Course</th>
    </tr>
  </thead>
  <!-- 遍历每个分类 -->
  <tbody ng-repeat="category in organization">
    <!-- 遍历每个科目,用ng-repeat-start标记循环开始 -->
    <tr ng-repeat-start="subject in category.subjectList">
      <!-- 只有当前分类的第一个科目才显示分类单元格,合并对应行数 -->
      <td ng-if="$first" rowspan="{{ getCategoryRowspan(category) }}">{{ category.categoryName }}</td>
      <!-- 科目单元格,合并对应课程行数 -->
      <td rowspan="{{ getSubjectRowspan(subject) }}">
        {{ subject.subjectname || subject.name }}
      </td>
      <!-- 显示第一个课程,或者占位符 -->
      <td>
        {{ subject.courseList.length > 0 ? subject.courseList[0].coursename : '-' }}
      </td>
    </tr>
    <!-- 遍历当前科目下剩下的课程,用ng-repeat-end标记循环结束 -->
    <tr ng-repeat-end ng-repeat="course in subject.courseList track by $index" ng-if="$index > 0">
      <!-- 只显示课程列,前两列被合并单元格覆盖 -->
      <td>{{ course.coursename }}</td>
    </tr>
  </tbody>
</table>

关键逻辑解释

  1. 数据预处理:把所有字符串格式的列表转成数组,统一课程名称字段,避免渲染时因为格式不一致出错。
  2. rowspan计算:
    • 分类的rowspan:计算该分类下所有科目对应的总行数(每个科目有n门课就占n行,没课占1行)。
    • 科目的rowspan:对应课程的数量,没课就占1行。
  3. 循环结构:用ng-repeat-start和ng-repeat-end实现“一个科目对应多行(课程行)”的逻辑,保证HTML结构合法。
  4. 特殊情况处理:比如没有课程的科目,显示-占位符;第一个科目才显示分类单元格,避免重复。

这样修改后,就能实现你想要的:分类相同合并单元格,科目相同合并单元格,课程按行排列的效果啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:25:47