0

I'm doing some testing with Angular to see if I can replicate what I already have in PHP more efficiently.

I have a set of data stored in JSON:

[
    {
        "name":"Blue Widget",
        "description":"blue-widget",
        "snippet":"The best blue widget around!",
        "category":"Home Widgets",
        "popular":true
    },
    {
        "name":"Red Widget",
        "description":"red-widget",
        "snippet":"The best red widget around!",
        "category":"Outdoor Widgets",
        "popular":true
    },
    {
        "name":"Green Widget",
        "description":"green-widget",
        "snippet":"The best green widget around!",
        "category":"Work Widgets",
        "popular":true
    },
    {
        "name":"Yellow Widget",
        "description":"yellow-widget",
        "snippet":"The best yellow widget around!",
        "category":"Home Widgets",
        "popular":true
    }
]

I'm grabbing this in my controller and adding it to my view in a fairly standard way (yes, I know not to use $http directly in a controller in production):

widgetApp.controller('widgetListCtrl', function($scope,$http){
    $http.get('widgets/widgets.json').success(function(data){
        $scope.widgets = data
    })
})

If I use:

<li ng-repeat="widget in widgets">{{widget.category}}</li>

Then naturally it will just go through and list:

Home Widgets
Outdoor Widgets
Work Widgets
Home Widgets

What I'd like to do is generate a list of each widget.category but with each category only appearing once, so a user could then click on a category and be shown all the widgets in that category. How can I go about this? Sorry, I haven't got anything to go on because I pretty much have no idea where to start.

user4676723
  • 134
  • 11

4 Answers4

0

You'd have to build a list of unique categories:

widgetApp.controller('widgetListCtrl', function($scope,$http){
    $http.get('widgets/widgets.json').success(function(data){
        $scope.uniqueCategories = [];
        for (var i = 0; i < $scope.widgets.length; i++) {
            if ($scope.uniqueCategories.indexOf($scope.widgets[i].category) === -1)
                $scope.uniqueCategories.push($scope.widgets[i].category);
        }
    });
});

Make a dropdown with the model set to the category:

<select ng-model="categoryFilter" ng-options="category as category for category in uniqueCategories"></select>

And use a filter on your repeat:

<li ng-repeat="widget in widgets | filter: { category: categoryFilter }">{{widget.category}}</li>
tymeJV
  • 103,943
  • 14
  • 161
  • 157
0

Create a filter

app.filter('unique', function() {
    return function (arr, field) {
        return _.uniq(arr, function(a) { return a[field]; });
    };
});

In Markup

<li ng-repeat="widget in widgets | unique:'category'">{{widget.category}}</li>
Vinay K
  • 5,562
  • 1
  • 18
  • 27
  • Reference: http://stackoverflow.com/questions/15914658/angular-js-how-to-make-ng-repeat-filter-out-duplicate-results – Vinay K Mar 19 '15 at 14:24
0

You can use the existing 'unique' filter from AngularUI.

<li ng-repeat="widget in widgets | unique: 'widget.category' ">{{widget.category}}</li>

Be sure to include a reference to the filters module in your app as well (e.g. angular.module('yourModule', ['ui', 'ui.filters']);).

rageandqq
  • 2,221
  • 18
  • 24
  • I've tried this but can't seem to get it to work - I've downloaded the `ui-utils.js` file and referenced it in my HTML, and DI'ed it in my angular module, but it throws an injector error. I'm doing something wrong :) – user4676723 Mar 19 '15 at 14:34
  • What does the injector error say? Use `angular.js` instead of `angular.min.js` to get a more detailed error message. – rageandqq Mar 19 '15 at 15:04
  • 1
    I've got it - I was using the wrong dependency name in my module - it was `ui-utils`. – user4676723 Mar 19 '15 at 16:05
0

Create a distinct filiter and use it on your view:

angular.filter("distinct", function () {
  return function (data, propertyName) {
     if (angular.isArray(data) && angular.isString(propertyName)) {
        var results = [];
        var keys = {};
        for (var i = 0; i < data.length; i++) {
           var val = data[i][propertyName];
           if (angular.isUndefined(keys[val]) && val != null) {
              keys[val] = true;
              results.push(val);
           };
        };
        return results;
     }
     else {
        return data;
     }
  }
})

<li ng-repeat="widget in widgets | distinct:'category'">{{widget.category}}</li>
Norbor Illig
  • 658
  • 6
  • 14