Search code examples
htmlangularjshtml-listsangular-ng-if

Create ul lists dynamically from one array


I am working with angularjs (version 1), I know it's old, but I need to work with this version.

I have this list

products = [
{
    "productID": 1,
    "productName": "product1",
    "productCategoryName": "category1"

},
{
    "productID": 2,
    "productName": "product2",
    "productCategoryName": "category1"
},
{
    "productID": 3,
    "productName": "product3",
    "productCategoryName": "category1"
},
{
    "productID": 4,
    "productName": "product4",
    "productCategoryName": "category2"
},
{
    "productID": 5,
    "productName": "product5",
    "productCategoryName": "category2"
},
{
    "productID": 6,
    "productName": "product6",
    "productCategoryName": "category3"
}];

My html code (it's incorrect):


    <div class="form-group">
        <div ng-repeat="product in vm.products | groupBy: 'productCategoryName'">    
            {{ product.productCategoryName}}
            <ul>
                <li>
                    <input type="checkbox" class="form-check-input" name="something">
                    <label> {{ product.productName }}</label>
                </li>
            </ul>
        </div>
    </div>

The result I want is to be able to create a ul for every productCategoryName, something like this:

<h3>category1</h3>
                        <ul>
                            <li>product1</li>
                            <li>product2</li>
                            <li>product3</li>
                        </ul>
                        <h3>category2</h3>
                        <ul>
                            <li>product4</li>
                            <li>product5</li>
                        </ul>
                        <h3>category3</h3>
                        <ul>
                            <li>product6</li>
                        </ul>

I can check if this is true: <ul ng-if="vm.products[$index - 1].productCategoryName !== product.productCategoryName ">

So I can create a new list when the current index has different category, but my problem here is that I cannot control the closing of the list I am not sure how can I fix this, would be great if you an help. Thanks!


Solution

  • This is one way of doing it.

    <html>
    <body ng-app="myapp" ng-controller="mycontroller">
    <div class="form-group">
      <div ng-repeat="productGroup in groups">
        <div>
          {{ productGroup.productCategoryName}}
          </div>
          <ul>
            <li ng-repeat="(key, value) in productGroup">
              <input type="checkbox" class="form-check-input" name="something">
              <label> {{ value.productName }}</label>
            </li>
          </ul>        
        </div>
      </div>
    </body>
    </html>
    
    angular.module('myapp', []).controller('mycontroller', function($scope, $filter){
        $scope.products = [
        {
            "productID": 1,
            "productName": "product1",
            "productCategoryName": "category1"
    
        },
        {
            "productID": 2,
            "productName": "product2",
            "productCategoryName": "category1"
        },
        {
            "productID": 3,
            "productName": "product3",
            "productCategoryName": "category1"
        },
        {
            "productID": 4,
            "productName": "product4",
            "productCategoryName": "category2"
        },
        {
            "productID": 5,
            "productName": "product5",
            "productCategoryName": "category2"
        },
        {
            "productID": 6,
            "productName": "product6",
            "productCategoryName": "category3"
        }];
    
        $scope.groups = $filter('groupBy')($scope.products, 'productCategoryName');
    })
    .filter("groupBy",["$parse","$filter",function($parse,$filter){
      return function(array, groupByField){
        var result  = {};
    
          var prev_item = null;
          var groupKey = false;
          var filteredData = $filter('orderBy')(array, groupByField);
    
            for(var i=0; i < filteredData.length; i++) {        
            if (!result[filteredData[i][groupByField]]) {
                result[filteredData[i][groupByField]] = [];
              result[filteredData[i][groupByField]].productCategoryName = filteredData[i][groupByField];
            }
    
            result[filteredData[i][groupByField]].push(filteredData[i]);
          }
    
          return result;
      }
    }])
    
    

    https://jsfiddle.net/8hscydq9/1/

    To help with performance, you can create the group ahead of time and then display that group. Otherwise, on every angular digest it will be recreating the group.