3

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>
Tropicalista
  • 3,097
  • 12
  • 44
  • 72

2 Answers2

5

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!

Brian Genisio
  • 47,787
  • 16
  • 124
  • 167
  • 1
    That isin't an acceptable answer. If you notice in the console, you will see that it's causing infinite digests. – plalx Dec 11 '13 at 13:09
  • @plalx Good point. I can fix this. I'll try to get that up. Thanks! – Brian Genisio Dec 11 '13 at 17:12
  • The only way I managed to fix it in my application was to perform the grouping in the controller and expose a `groupedItems` property on the `$scope`. I am not sure it's the best or only way however. You can put a watch on `friends` to make sure the groupings are updated when `friends` changes. – plalx Dec 11 '13 at 17:39
  • @plalx Yeah, I've updated it. Using a function to return a different array every time causes the `$digest` to fire over and over again. The better way to do it (and no more code than before) is to watch the `grouping` property and group the data into a new property. – Brian Genisio Dec 11 '13 at 18:12
  • 2
    Kudos for the Arrested Dev ref. – treejanitor Oct 19 '14 at 09:45
  • I tested it and i want to know how to hide empty or inexistant key and value like this example with no name: {gender: "Female",hair: "Black"} It show a empty
  • – Gino Mar 23 '17 at 22:23