AngularJS Group By Directive without External Dependencies

前端 未结 9 962
长发绾君心
长发绾君心 2020-11-29 01:01

I\'m new to Angular and would like to learn the best way to handle a problem. My goal is to have a reusable means to create group by headers. I created a solution which wor

相关标签:
9条回答
  • 2020-11-29 01:25

    http://blog.csdn.net/violet_day/article/details/17023219#t2

    <!doctype html>  
    <html ng-app>  
    <head>  
        <script src="lib/angular/angular.min.js"></script>  
        <script>  
            function TestCtrl($scope) {  
                $scope.items = [  
                    { id: 0, name: "Red"},  
                    { id: 1, name: "Red"},  
                    { id: 2, name: "Red"},  
                    { id: 3, name: "Red"},  
                    { id: 4, name: "Yellow"},  
                    { id: 5, name: "Orange"}  
                ];  
            }  
        </script>  
    </head>  
    <body ng-controller="TestCtrl">  
    <ul ng-repeat="a in items" ng-if="a.name!=items[$index-1].name">  
        {{ a.name }}  
        <li ng-repeat="b in items" ng-if="a.name==b.name">  
            {{ b.id }}  
        </li>  
    </ul>  
    </body>  
    </html>  
    
    0 讨论(0)
  • 2020-11-29 01:28

    EDIT: here's a custom filter approach. Groups is created by a filter function in scope to generate array of groups from current list. Adding/deleting list items will bind update of the group array as it is reset every digest cycle.

    HTML

    <div ng-app="myApp">
        <div ng-controller='TestGroupingCtlr'>
            <div ng-repeat='group in getGroups()'>
                 <h2>{{group}}</h2>
                  <ul>
                    <!-- could use another scope variable as predicate -->
                    <li ng-repeat="item in MyList |  groupby:group">{{item.whatever}}</li>
                </ul>
            </div>
        </div>
    </div>
    

    JS

    var app=angular.module('myApp',[]);
    app.filter('groupby', function(){
        return function(items,group){       
           return items.filter(function(element, index, array) {
                return element.GroupByFieldName==group;
            });        
        }        
    })        
    
    app.controller('TestGroupingCtlr',function($scope) {
    
        $scope.MyList = [{  GroupByFieldName: 'Group 1', whatever: 'abc'},
                         {GroupByFieldName: 'Group 1',whatever: 'def'}, 
                         {GroupByFieldName: 'Group 2',whatever: 'ghi' },
                         {GroupByFieldName: 'Group 2',whatever: 'jkl'}, 
                         {GroupByFieldName: 'Group 2',whatever: 'mno'  }
                        ];
        $scope.getGroups = function () {
            var groupArray = [];
            angular.forEach($scope.MyList, function (item, idx) {
                if (groupArray.indexOf(item.GroupByFieldName) == -1)
                  groupArray.push(item.GroupByFieldName)
            });
            return groupArray.sort();
        }
    
    })
    

    DEMO

    0 讨论(0)
  • 2020-11-29 01:30

    If you are already using LoDash/Underscore, or any functional library, you can do this using _.groupBy() (or similarly named) function.


    In controller:

    var movies = [{"movieId":"1","movieName":"Edge of Tomorrow","lang":"English"},
                  {"movieId":"2","movieName":"X-MEN","lang":"English"},
                  {"movieId":"3","movieName":"Gabbar Singh 2","lang":"Telugu"},
                  {"movieId":"4","movieName":"Resu Gurram","lang":"Telugu"}];
    $scope.movies = _.groupBy(movies, 'lang');
    

    In template:

    <ul ng-repeat="(lang, langMovs) in movies">{{lang}}
      <li ng-repeat="mov in langMovs">{{mov.movieName}}</li>
    </ul>
    

    This will renders:

    English

    • Edge of Tomorrow
    • X-MEN

    Telugu

    • Gabbar Singh 2
    • Resu Gurram

    Even better, this can be also converted into a filter very easily, without much of boilerplate code to group elements by a property.

    Update: Group by multiple keys

    Often grouping using multiple keys is very useful. Ex, using LoDash (source):

    $scope.movies = _.groupBy(movies, function(m) {
        return m.lang+ "-" + m.movieName;
    });
    

    Update on why I recommend this approach: Using filters on ng-repeat/ng-options causes serious perf issues unless that filter executes quickly. Google for the filters perf problem. You'll know!

    0 讨论(0)
提交回复
热议问题