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

Angular表格点击行展开详情时所有行数据重复问题求助

嘿,这个问题我太熟啦!你碰到的是AngularJS里很常见的全局变量共享导致数据覆盖的问题,咱们一步步拆解原因,再给出解决方案:

问题根源

你现在的代码里,$scope.childPar和viewChild都是全局的$scope变量:

  • 每次点击任意一行,$scope.childPar都会被更新成当前行对应的子数据,而所有展开行的模板都绑定了这个全局变量,所以不管点哪一行,所有展开的地方都会显示最后一次赋值的childPar数据。
  • 全局的viewChild加上indx!=$index的判断虽然能勉强控制显示,但这种依赖全局状态的写法很容易出bug,逻辑也不清晰。
解决方案:把数据和状态绑定到每个用户对象上

我们需要让每一行的展开状态和对应的子数据,都属于当前行的user对象,而不是用全局变量来共享。

1. 改造Controller代码

'use strict';
angular.module('sbAdminApp')
.controller('TreeTableCtrl', TreeTableCtrl);

function TreeTableCtrl($scope, $http, factor) {
    function example() {
        factor.getUse().then(function (response) {
            $scope.users = response.data;
            // 给每个用户初始化展开状态和子数据存储属性
            $scope.users.forEach(user => {
                user.isExpanded = false; // 标记是否展开
                user.childData = null; // 存储当前用户的子数据
            });
            console.log($scope.users);
        });
    }
    example();

    $scope.togglePerson = function (user) {
        // 先切换当前用户的展开状态
        user.isExpanded = !user.isExpanded;
        
        // 如果是展开操作,且还没加载过子数据,再发起请求
        if (user.isExpanded && !user.childData) {
            factor.getChi().then(function (response) {
                // 这里注意:如果你的子数据是按用户id关联的,建议用id匹配而不是index
                // 比如 user.childData = response.data.find(item => item.parentId === user.id);
                const userIndex = $scope.users.indexOf(user);
                user.childData = response.data[userIndex];
                console.log(user.childData);
            });
        }
    };
}

2. 改造HTML模板

现在模板可以直接用每个user自身的状态和数据,不用再依赖全局变量:

<div class="panel panel-default" style="background: #fcf8e3">
    <div class="panel-body">
        <table st-safe-src="leads" class="table table-hover ">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Name</th>
                    <th>Last Name</th>
                </tr>
            </thead>
            <tbody>
                <tr ng-repeat-start="user in users track by $index" ng-click="togglePerson(user)">
                    <td> {{user.id}}</td>
                    <td>{{user.name}}</td>
                    <td>{{user.lastName}}</td>
                </tr>
                <!-- 直接用user.isExpanded控制显示,数据绑定user.childData -->
                <tr ng-show="user.isExpanded">
                    <td style="width: 450px" colspan="3">
                        <table class="table ">
                            <tbody>
                                <tr>
                                    <th style="width: 200px"> Address </th>
                                    <td style="width: 200px">{{user.childData.address}}</td>
                                    <th style="width: 200px"> Number </th>
                                    <td style="width: 200px">{{user.childData.mobNumb}}</td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                </tr>
                <tr ng-repeat-end></tr>
            </tbody>
        </table>
    </div>
</div>

额外小建议

  • 不要用index匹配数据:如果你的用户数据和子数据是通过id关联的(比如子数据里有parentId对应用户的id),一定要用id去匹配,而不是数组索引。因为如果数组顺序变化,索引匹配就会出错,用id更可靠,比如:
    user.childData = response.data.find(item => item.parentId === user.id);
    
  • 避免重复请求:上面的代码里加了!user.childData的判断,只有第一次展开时才会请求子数据,重复点击同一行不会重复发请求,性能更好。

内容的提问来源于stack exchange,提问作者Ivan Luketić

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:17:52