Tropicalista
Tropicalista

Reputation: 3137

AngularJs grouping by property

I need a way to order a list by its properties.

I have this plunker: http://jsfiddle.net/Tropicalista/aF2aL/1/

but don't know hoe to proceed. I need a way to order the list based on what I select in checkboxes...

function myCtrl($scope){
    $scope.friends = [

    {
        name: "Michael",
        gender: "Male",
        hair: "Brunette"
    },
    {
        name: "George Michael",
        gender: "Male",
        hair: "Brunette"
    },
    {
        name: "Gob",
        gender: "Male",
        hair: "Brunette"
    },
    {
        name: "Tobias",
        gender: "Male",
        hair: "Black"
    },
    {
        name: "Lindsay",
        gender: "Female",
        hair: "Blonde"
    },
    {
        name: "Maeby",
        gender: "Female",
        hair: "Black"
    }
];
$scope.orderBy = function(target){
    $scope.groups = _.groupBy($scope.friends, target);
}
$scope.activeGroups = {};

}

And this is my html:

<input type="checkbox" ng-click="orderBy('name')" />Name
<input type="checkbox" ng-click="orderBy('gender')" />Gender
<input type="checkbox" ng-click="orderBy('hair')" />Hair

<div data-ng-repeat="(myFilter, users) in groups">
    <h2>{{myFilter}}</h2>        
    <ul>
        <li data-ng-repeat="user in users">
        {{ user.name }}
        </li>
    </ul>
</div>

Upvotes: 3

Views: 9183

Answers (2)

a8m
a8m

Reputation: 9474

You can use groupBy of angular.filter module, It's easy to use, and actually more fast than lodash implementation see: link.
Usage: (key, val) in collection | groupBy: 'property' or nested.property
here's an example:

JS:

$scope.players = [
  {name: 'Gene', team: 'alpha'},
  {name: 'George', team: 'beta'},
  {name: 'Steve', team: 'gamma'},
  {name: 'Paula', team: 'beta'},
  {name: 'Scruath', team: 'gamma'}
];

HTML:

<ul ng-repeat="(key, value) in players | groupBy: 'team'">
  Group name: {{ key }}
  <li ng-repeat="player in value">
    player: {{ player.name }} 
  </li>
</ul>

RESULT:
Group name: alpha
* player: Gene
Group name: beta
* player: George
* player: Paula
Group name: gamma
* player: Steve
* player: Scruath

UPDATE: jsbin

Upvotes: 3

Brian Genisio
Brian Genisio

Reputation: 48137

First, for something like this, I much prefer using a radio instead of a checkbox. It is semantically correct. Check boxes indicate that you can group by more than one field, and it doesn't appear, from your question, that you are trying to do that.

Knowing that, you can define your radios like this:

<input type="radio" ng-model="grouping" value="name"  />Name
<input type="radio" ng-model="grouping" value="gender" />Gender
<input type="radio" ng-model="grouping" value="hair" />Hair

Now, you can just tell your ng-repeat to group based on a groupedFriends collection:

<div data-ng-repeat="(group, users) in groupedFriends">
    <h2>{{group}}</h2>        
    <ul>
        <li data-ng-repeat="user in users">
            {{ user.name }}
        </li>
    </ul>
</div>

And then your controller just watches the grouping variable and group the data:

$scope.$watch('grouping', function() {
    $scope.groupedFriends = _.groupBy($scope.friends, $scope.grouping);
});

$scope.grouping = "gender";

Here is a working fiddle.

STEVE HOLT!

Upvotes: 5

Related Questions