使用 Angular ng-repeat 迭代对象数组的非均匀性

Iterating through non uniform of array of objects with Angular ng-repeat

假设我有以下数据:

sampleData = [{'artist': 'John', 'id': 1}, {'artist': 'John', 'id': 2},
{'artist': 'Tim', 'id': 3}, {'artist': 'Jimmy', 'id': 4}, {'venue': 'Rock club', 'id':1}, {'venue': 'Rock club', 'id': 2}, {'venue': 'Tonys', 'id': 3}]

这个数据可以在我的控制器中找到并且不会改变。我想要做的是在主 <ul> 中构建两个嵌套列表。

鉴于我有以下输入,其中用户键入 'J' 或 'j':

<input ng-model="query" type="text" placeholder="Filter by">

这是我想使用 ng-repeat 渲染的内容(除非我不必使用 ng-repeat):

<ul>
  <h1>artist</h1>
  <li>
    <ul>
      <li>John (There are two 2 Johns)</li>
      <li>Jimmy</li>
    </ul>
  </li>
  <li>
    <ul>
    <h1>Venue</h1>
      <li>Jock Club (There are two 2 Jock Club)</li>
    </ul>
  </li>
</ul>

最初,我尝试编写一个客户过滤器,从过滤列表中获取结果并处理数据。 Angular 对我的过滤器不满意,因为我对原始数据的修改太多,所以我收到了一个无限摘要循环。所以现在我回到原点,试图决定这是最好用指令还是过滤器来完成。我怀疑我需要在我的控制器或指令中重组我的数据以获得我想要的结果。同样,我的预期结果将是根据用户输入的内容过滤 sampleData 的艺术家和场地子列表。实时更新是最理想的。

如果您不想重组您的数据,可以通过在您的控制器中使用函数来实现,这些函数使用过滤器只为每个 ng-repeat 获取您想要的项目:

在控制器中:

var sampleData = [...];
$scope.query = '';

$scope.getArtists = function () {
   return $filter('filter')(sampleData, function (item) {
       return item.hasOwnProperty('artist') && item.artist.indexOf($scope.query) > -1; 
   });
};

$scope.getVenues = function () {
   return $filter('filter')(sampleData, function (item) {
       return item.hasOwnProperty('venue') && item.venue.indexOf($scope.query) > -1;  
   });
};

HTML:

<input ng-model="query" type="text" placeholder="Filter by">
<ul>
    <li ng-repeat="artist in getArtists()"></li>
</ul>
<ul>
    <li ng-repeat="venue in getVenues()"></li>
</ul>

------------

但是,最好预先重组您的数据,这样您就可以使用单个函数更有效地遍历场地和艺术家:

在控制器中:

var sampleData = [...];
$scope.query = '';
$scope.artists = [];
$scope.venues = [];

angular.forEach(sampleData, function (item) {
    if (item.hasOwnProperty('artist') {
        $scope.artists.push({
            id: item.id,
            name: item.artist
        });
    });
    else if (item.hasOwnProperty('venue') {
        $scope.venues.push({
            id: item.id,
            name: item.venue
        });
    });
});

$scope.getMatching = function (items, query) {
    return $filter('filter')(items, function (item) {
        return (item.name.indexOf(query) > -1); 
    });
};

HTML:

<input ng-model="query" type="text" placeholder="Filter by">
<ul>
    <li ng-repeat="artist in getMatching(artists, query)"></li>
</ul>
<ul>
    <li ng-repeat="venue in getMatching(venues, query)"></li>
</ul>