5

I have array of categories that has this structure:

{
name: 'something',
main_category: 'A'
}

So each category has it's main category. I would like to display all categories in html like so:

<h1>A</h1>
<ul>
<li>list of categories that has main category A</li>
</ul>
<h1>B</h1>
<ul>
<li>list of categories that has main category B</li>
</ul>

how should I achieve it? The only way I found was doing something like this:

<h1>A</h1>
<ul>
<li ng-repeat="category in categories" ng-if="category.main_category == 'A'">..</li>
</ul>
<h1>B</h1>
<ul>
<li ng-repeat="category in categories" ng-if="category.main_category == 'B'">..</li>
</ul>

It works but I don't think it's a good idea.

dontHaveName
  • 1,899
  • 5
  • 30
  • 54

3 Answers3

5

You should use groupBy filter provided by https://github.com/a8m/angular-filter, and do something like this

var myApp = angular.module('mcApp', ['angular.filter']);

myApp.controller('mcController', ['$scope', function ($scope) {
        console.log('asadsds');
        $scope.myArray = [
          {
            name: 'something 1',
            main_category: 'B'
          },
          {
            name: 'something 2',
            main_category: 'A'
          },
          {
            name: 'something 3',
            main_category: 'A'
          },
          {
            name: 'something 4',
            main_category: 'B'
          },
          {
            name: 'something 5',
            main_category: 'B'
          }
          ];
  
}]);
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Example - example-example7-production</title>
  

  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.0-beta.5/angular.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.5/angular-filter.js"></script>
  <script src="app.js"></script>
  

  
</head>
<body ng-app="mcApp" ng-controller="mcController">
<p>{{name}}</p>

<div ng-repeat="object in myArray | orderBy: 'main_category'| groupBy:'main_category' |toArray: true" >
  <h1>{{object.$key}}</h1>
  <ul>
    <li ng-repeat="value in object">
      {{value.name}}
    </li>
  </ul>
</div>

</body>
</html>
Mudasser Ajaz
  • 6,197
  • 1
  • 26
  • 29
2

See this answer for how to use Angular's filter: { prop: 'value' } syntax to achieve the same functionality as an ng-if in this use-case:

<h1>A</h1>
<ul>
    <li ng-repeat="category in categories | filter: {main_category: 'A'}"></li>
</ul>

<h1>B</h1>
<ul>
    <li ng-repeat="category in categories | filter: {main_category: 'B'}"></li>
</ul>
sdgluck
  • 24,894
  • 8
  • 75
  • 90
0

You can do it by creating a second main categories array. Using ng-repeat-start and ng-repeat-end you create the basic structure (h1 + ul). In the ul a second repeater of categories filtered by the main category renders the list items (fiddle):

<div ng-app ng-controller="MyCtrl">
     <h1 ng-repeat-start="mainCategory in mainCategories | orderBy">{{mainCategory}}</h1> 
    <!-- main categories ngRepeat starts here -->
    <ul ng-repeat-end>
        <!-- main categories ngRepeat ends here -->
        <li ng-repeat="category in categories | orderBy:'name' | filter:{ 'main_category': mainCategory}">{{category.name}}</li>
        <!-- categories are filtered by mainCategory -->
    </ul>
</div>


function MyCtrl($scope) {
    var categories = [{
        name: 'somethingA2',
        main_category: 'A'
    }, {
        name: 'somethingB1',
        main_category: 'B'
    }, {
        name: 'somethingB2',
        main_category: 'B'
    }, {
        name: 'somethingA3',
        main_category: 'A'
    }, {
        name: 'somethingB3',
        main_category: 'B'
    }, {
        name: 'somethingA1',
        main_category: 'A'
    }];

    $scope.categories = categories;

    /** main categories - reduce the categories array to a dictionary object, and get the keys of the dictionary to get the unique main category names **/
    $scope.mainCategories = Object.keys(categories.reduce(function (main, category) {
        main[category['main_category']] = '';
        return main;
    }, {}));
}
Ori Drori
  • 183,571
  • 29
  • 224
  • 209