bofanda
bofanda

Reputation: 11826

Skip duplicated items while ng-repeat

There is a nested array which consist of bundles and those bundles in turn have items. So, I want to skip identical item(s) of the next bundle based on previous bundle items while iterating. Below is data model and code snippets:

vm.data

[
  {
    id: '01',
    name: 'Dummy1',
    items: [{
      id: 'itemOne',
      name: 'ItemOne',
      desc: 'ItemOne description'
    }]
  },
  {
    id: '02',
    name: 'Dummy2',
    items: [{
      id: 'itemOne',
      name: 'ItemOne',
      desc: 'ItemOne description'
    },
    {
      id: 'otherItem',
      name: 'OtherItem',
      desc: 'OtherItem description'
    }]
  },
  ...
]

Html:

<div ng-repeat="bundle in vm.data track by $index">
  ...
  <ul>
    <li ng-repeat="item in bundle.items" ng-if="vm.check(item, $parent.$index)">
      <span ng-bind="item.name"></span>
      ...
    </li>
  </ul>
</div>

vm.check:

vm.check = function(item, bundleIdx) {
  if (bundleIdx > 0) {
    return _.some(vm.data[bundleIdx-1].items, function(obj) {
      return obj.id !== item.id;
    });
  } else {
    // first bundle, so show all items
    return true;
  }
};

Demo is here.

It works partially, i.e. second bundle correctly matches conditions, but third bundle not. So, what I'm missing? Any help would be appreciated!

Upvotes: 0

Views: 44

Answers (1)

Jake Holzinger
Jake Holzinger

Reputation: 6063

I would keep the complex logic out of your template. Instead you should transform vm.data before you attempt to consume it.

var items = {};
vm.bundles = [];
vm.data.forEach(function(data) {

    var bundle = {
        id: data.id,
        name: data.name,
        items: []
    };

    data.items.forEach(function(item) {
        if (!items[item.id]) {
            bundle.items.push(item);
        }
        items[item.id] = true;
    });

    vm.bundles.push(bundle);
});

Then your template can simply consume the transformed data.

<div ng-repeat="bundle in vm.bundles track by $index">
    ...
    <ul>
        <li ng-repeat="item in bundle.items">
            <span>{{item.name}}</span>
            ...
        </li>
    </ul>
</div>

Upvotes: 1

Related Questions