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ć
相关产品推荐
相关产品推荐

