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

AngularJS中ngRepeat如何跳过$$hashKey?动态表格列名问题

AngularJS: ng-if Not Hiding $$hashKey Column & Correct Column Name Retrieval

Let's break down your issues step by step, starting with a recap of your setup: you're trying to dynamically generate tables from an object where each category (from the categories array) maps to an array of items. Right now, you're seeing an unexpected $$hashKey column even though you added an ng-if condition to exclude it, and you're unsure about the proper way to fetch column names.

Your Data Structure

{ 
  categories: ["kids", "home"], 
  home: [
    { name: "home 1.1", title: " home1.2" }, 
    { name: "home 2.1", title: "home 2.2" }, 
    { name: "home 3.1", title: "home 3.2" }, 
    { name: "home 4.1", title: "home 4.2" }, 
    { name: "home 5.1", title: "home 5.2" }
  ], 
  kids: [{ name: "kids 1.1", title: "kids 1.2" }] 
}

Your Current Code

JavaScript

var app = angular.module("app", []); 
app.controller("MainCtrl", function($scope) { 
  $scope.data = { /* ... your data as above ... */ }; 
  $scope.getKeys = function(obj) { 
    if (!$scope.data.hasOwnProperty(obj)) { 
      return []; 
    } 
    return Object.keys($scope.data[obj][0]); 
  } 
});

HTML

<html ng-app="app"> 
<head> 
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js"></script> 
</head> 
<body ng-controller="MainCtrl"> 
  <table ng-repeat="d in data.categories"> 
    <tr> 
      <th ng-repeat="l in getKeys(d)" ng-if="$index != getKeys(d).length - 1"> 
        {{$index != getKeys(d).length - 1}} {{l}} 
      </th> 
    </tr> 
    <tr ng-repeat="k in data[d]"> 
      <td>{{k.name}}</td> 
      <td>{{k.title}}</td> 
    </tr> 
  </table> 
</body> 
</html>

1. Why is the $$hashKey column showing even when the ng-if condition is false?

First, know that AngularJS automatically adds a $$hashKey property to objects in arrays used with ng-repeat—this helps it track items efficiently for updates. When you call Object.keys($scope.data[obj][0]), it includes this internal property, making your keys array longer than you intended.

As for why your ng-if isn't hiding it: Angular runs frequent digest cycles, and every cycle re-executes your getKeys(d) function. This means the array returned by getKeys is a new reference each time, causing ng-repeat to re-render the <th> elements. The $index and getKeys(d).length don't align consistently during these cycles, so the final column (with $$hashKey) slips through.

On top of that, object key order wasn't guaranteed in older JavaScript versions, so assuming $$hashKey is always the last key isn't reliable even if the digest cycle wasn't an issue.

2. What's the correct way to get table column names?

You need to explicitly exclude Angular's internal properties like $$hashKey when fetching your column keys. Here are three solid approaches:

Option 1: Filter out internal properties in getKeys

Modify your getKeys method to exclude any keys starting with $$ (Angular's convention for internal properties):

$scope.getKeys = function(obj) {
  if (!$scope.data.hasOwnProperty(obj) || $scope.data[obj].length === 0) {
    return [];
  }
  // Filter out keys starting with $$
  return Object.keys($scope.data[obj][0]).filter(key => !key.startsWith('$$'));
};

Now you can remove the ng-if entirely from your <th> since $$hashKey is never included in the keys array:

<th ng-repeat="l in getKeys(d)"> {{l}} </th>

Option 2: Use angular.toJson to strip internal properties

Angular's angular.toJson method automatically removes properties starting with $$. Convert the object to JSON and parse it back to get a clean version:

$scope.getKeys = function(obj) {
  if (!$scope.data.hasOwnProperty(obj) || $scope.data[obj].length === 0) {
    return [];
  }
  // Strip internal properties and get keys
  const cleanObj = angular.fromJson(angular.toJson($scope.data[obj][0]));
  return Object.keys(cleanObj);
};

Option 3: Preprocess data upfront

If you don't need $$hashKey at all, preprocess your data to remove these properties when initializing:

// In your controller
Object.keys($scope.data).forEach(key => {
  if (Array.isArray($scope.data[key])) {
    // Clean each item in the array
    $scope.data[key] = $scope.data[key].map(item => angular.fromJson(angular.toJson(item)));
  }
});

Your original getKeys function will now work without modification, since $$hashKey is already removed from all items.


Bonus: Make table rows fully dynamic

Right now you're hardcoding <td>{{k.name}}</td> and <td>{{k.title}}</td>. To make this fully dynamic (so it works even if your item structure changes), replace those with another ng-repeat using the keys you retrieved:

<tr ng-repeat="k in data[d]">
  <td ng-repeat="key in getKeys(d)">{{k[key]}}</td>
</tr>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 09:08:29