How to select objects that have a certain atribute in a json file in an Angular JS project? - angularjs

I have a link to an API which lists movies, each movie has title,id etc...
API: http://private-5d90c-kevinhiller.apiary-mock.com/angular_challenge/horror_movies
It also has an offers array inside which contains a 'provider_id' property.
I need to show how many movies are available at which provider.
But I dont know how, the best I came up with was:
{{movie.offers[0].provider_id}}
But that only shows the first provider on each movie.
What I want is to extract how many movies each provider has.
My Html:
<div ng-controller="ProviderController as provider">
<div ng-repeat="movie in provider.movies">
{{movie.offers[0].provider_id}}
</div>
</div>
My Main.js:
app.controller('ProviderController', function($http) {
var provider = this;
provider.movies = [];
$http({
url: 'some/path/horror_movies',
method: "GET",
}).success(function(data) {
provider.movies = data;
});
});
Also this is the structire of the json file:
[{
"id": 140524,
"title": "Dracula Untold",
"offers": [{
"provider_id": 2,
"retail_price": 14.99,
//...
}, {
"provider_id": 2,
"retail_price": 14.99,
}, {
"provider_id": 7,
"retail_price": 14.99,
}, ]
},
{
"id": 138993,
"title": "The Purge: Anarchy",
"offers": [
// ...
]
},
]
Any ideas ? Thanks.

You will need to change the structure of your database to have providers at the top level. A function achieving something like this should iterate over every movies offers, something like this:
function getProviders (movies) {
var providers = [],
movie = {},
offer = {};
for (var i = 0, max = movies.length; i < max; i += 1) {
movie = movies[i];
for (var j = 0; j < movies[i].offers.length; j += 1) {
offer = movie.offers[j];
if (typeof providers[offer.provider_id] === 'undefined') {
providers[offer.provider_id] = { movies: [] };
}
providers[offer.provider_id].movies.push(movie);
}
}
return providers;
}
I started a fiddle here: http://jsfiddle.net/d29tu8fg/1/
Before adding a movie to a provider, you might also want to check, if that movie already exists. You only need to do that though, if – like in your data – a movie can have two different offers from the same provider.
Add the providers to the $scope and in your view show the length:
<div ng-repeat="provider in providers track by $index">
{{provider.movies.length}}
</div>

Related

How can I output Google Places details into a JSON file?

I'm trying to loop through Google Place IDs and gather data from each place and then output the place details into one single JSON file which could later be imported into a map. The importing stage is not a concern but I'm struggling to get the data into the JSON file to begin with. What I have currently is below.
<script src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=places&key=APIKEY"></script>
var placeid_list = [{
"placeid": 'ChIJryijc9s0K4gRG9aU7SDTXdA',
}, {
"placeid": 'ChIJaZ6Hg4iAhYARxTsHnDFJ9zE',
}, {
"placeid": 'ChIJl64IQXrYzUwR8CVOTRf_h3o',
}, {
"placeid": 'ChIJBTMkuph-zkwR9oEF8Nv3Z0o',
}, {
"placeid": 'ChIJ4QbSBj8IzkwRGi0ILu03_VA',
}, {
"placeid": 'ChIJc2nSALkEdkgRkuoJJBfzkUI',
}, {
"placeid": 'ChIJmzrzi9Y0K4gRgXUc3sTY7RU',
}];
function setPlaces() {
var json = placeid_list;
for (var i = 0, length = json.length; i < length; i++) {
var data = json[i];
createPlace(data);
}
}
function createPlace(data) {
var service = new google.maps.places.PlacesService();
service.getDetails({
placeId: data.placeid
}, function (result, status) {
if (status != google.maps.places.PlacesServiceStatus.OK) {
alert(status);
return;
}
placeResults(data, result);
});
}
function placeResults(data, result) {
console.log(result.name);
}
Currently I'm just trying to output each of the Place names into a console.log but nothing seems to be showing. It doesn't look like I'm getting any errors in the console either so I'm not too sure where I'm going wrong.
Looking at Google's documentation, I'm not sure if I have to make use of
console.log(JSON.stringify(response.data));
Would this help me to put the details of each of the places into one large JSON file? I'm not too sure how I can implement it with what I currently have. I don't have a great deal of expertise in using javascript but I'm hoping that I'm not too far away from a solution. Thanks
You a typo in youre code:
var service = new google.maps.places.PlacesService();
Per the documentation:
Constructor
PlacesService(attrContainer)
Parameters:
attrContainer: HTMLDivElement|Map
Creates a new instance of the PlacesService that renders attributions in the specified container.
The PlacesService constructor has a required argument, either a google.maps.Map object or an HTMLDivElement that can be used to render attributions.
So the referenced line should be:
var service = new google.maps.places.PlacesService(map);
Or:
var service = new google.maps.places.PlacesService(document.getElementById("attributionDiv");
// where attributionDiv is a div that is displayed on your page
Proof of concept fiddle
Outputs:
Alo
Ottawa International Airport
lastminute.com London Eye
Four Seasons Hotel San Francisco
CN Tower
Glenn P Cowan, Chartered Professional Accountant
KB Media Corp
code snippet:
// This example requires the Places library. Include the libraries=places
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places">
function initMap() {
const map = new google.maps.Map(document.getElementById("map"), {
center: {
lat: -33.866,
lng: 151.196
},
zoom: 15,
});
const request = {
placeId: "ChIJN1t_tDeuEmsRUsoyG83frY4",
fields: ["name", "formatted_address", "place_id", "geometry"],
};
const infowindow = new google.maps.InfoWindow();
const service = new google.maps.places.PlacesService(map);
var placeid_list = [{
"placeid": 'ChIJryijc9s0K4gRG9aU7SDTXdA',
}, {
"placeid": 'ChIJaZ6Hg4iAhYARxTsHnDFJ9zE',
}, {
"placeid": 'ChIJl64IQXrYzUwR8CVOTRf_h3o',
}, {
"placeid": 'ChIJBTMkuph-zkwR9oEF8Nv3Z0o',
}, {
"placeid": 'ChIJ4QbSBj8IzkwRGi0ILu03_VA',
}, {
"placeid": 'ChIJc2nSALkEdkgRkuoJJBfzkUI',
}, {
"placeid": 'ChIJmzrzi9Y0K4gRgXUc3sTY7RU',
}];
function setPlaces() {
var json = placeid_list;
for (var i = 0, length = json.length; i < length; i++) {
var data = json[i];
createPlace(data);
}
}
function createPlace(data) {
var service = new google.maps.places.PlacesService(map);
console.log(data);
service.getDetails({
placeId: data.placeid,
fields: ["name", "formatted_address", "place_id", "geometry"],
}, function(result, status) {
if (status != google.maps.places.PlacesServiceStatus.OK) {
alert(status);
return;
}
placeResults(data, result);
});
}
function placeResults(data, result) {
console.log(result.name);
document.getElementById("placeResults").innerHTML += result.name + "<br>";
}
setPlaces();
}
window.initMap = initMap;
/*
* Always set the map height explicitly to define the size of the div element
* that contains the map.
*/
#map {
height: 50%;
}
/*
* Optional: Makes the sample page fill the window.
*/
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<!DOCTYPE html>
<html>
<head>
<title>Place Details</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<!-- jsFiddle will insert css and js -->
</head>
<body>
<div id="placeResults"></div>
<div id="map"></div>
<!--
The `defer` attribute causes the callback to execute after the full HTML
document has been parsed. For non-blocking uses, avoiding race conditions,
and consistent behavior across browsers, consider loading using Promises
with https://www.npmjs.com/package/#googlemaps/js-api-loader.
-->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&libraries=places&v=weekly" defer></script>
</body>
</html>

How to split my JSON object in angularJS

I am trying to create pagination for my table that lists the objects returned from my DB as an object. My data structure will look something like:
$scope.myJSONObj = {
app1: {
id: 1,
appName: "appIntegrated1",
status: "Pending"
},
app2: {
id: 2,
appName: "appIntegrated2",
status: "Pending"
},
app3: {
id: 3,
appName: "appIntegrated3",
status: "Completed"
},
app4: {
id: 4,
appName: "appIntegrated4",
status: "Pending"
},
app5: {
id: 5,
appName: "appIntegrated5",
status: "Pending"
},
app6: {
id: 6,
appName: "appIntegrated6",
status: "Pending"
},
app7: {
id: 7,
appName: "appIntegrated7",
status: "Pending"
},
app8: {
id: 8,
appName: "appIntegrated8",
status: "Pending"
},
app9: {
id: 9,
appName: "appIntegrated9",
status: "Pending"
},
app10: {
id: 10,
appName: "appIntegrated10",
status: "Pending"
}
I am trying to split my structure in half, and display the first five results. I have a prev/next button, and when I click next, it should display the next 5 results (in this case the last 5). However, for everything to work, I need to be able to split my object, and so far every method I've researched involves arrays, and objects requiring some hack. I was wondering if I was missing something, or I have to create a solution to work with?
In pure JavaScript :
function getEntries(from, to) {
var entries = [];
for(var key in myJSONObj) {
// extract index after `app`
// var index = key.substring(3);
// Better way : extract index using regular expression, so it will match `something1`, `foo2`, `dummy3`
var index = parseInt(key.replace( /^\D+/g, ''));
if(index >= from && index <= to) {
entries.push(myJSONObj[key]);
}
}
return entries;
}
console.log(getEntries(0, 5));
Try _.chunk
https://lodash.com/docs/4.17.4#chunk
$scope.pages = _.chunk($scope.myJSONObj,5);
$scope.getPage = function( pageIndex ){
return $scope.pages[pageIndex];
}
It's untested - but I wrote a chunk method for you in vanilla JS since you can't use lodash.
function chunk(obj, chunkSize) {
var resultArray = [];
var resultArrayCurrentIndex = 0;
for (var key in obj) {
var item = obj[key];
if (resultArray[resultArrayCurrentIndex].length <= chunkSize) {
if (!resultArray[resultArrayCurrentIndex]) {
resultArray[resultArrayCurrentIndex] = [item];
} else {
resultArray[resultArrayCurrentIndex].push(item)
}
} else {
resultArrayCurrentIndex++
resultArray[resultArrayCurrentIndex] = [item];
}
}
return resultArray;
}
Then you can access it like this:
$scope.pages = chunk(yourObject, 5);
$scope.getPage = function(index){
return $scope.pages[index];
}
EDIT - changed it to accept an obj.
Used Object.keys, Array.prototype.slice and Array.prototype.reduce to solve your issue. Hope this helps
angular.module('app',[])
.controller('TestCtrl', function($scope){
$scope.myJSONObj = {"app1":{"id":1,"appName":"appIntegrated1","status":"Pending"},"app2":{"id":2,"appName":"appIntegrated2","status":"Pending"},"app3":{"id":3,"appName":"appIntegrated3","status":"Completed"},"app4":{"id":4,"appName":"appIntegrated4","status":"Pending"},"app5":{"id":5,"appName":"appIntegrated5","status":"Pending"},"app6":{"id":6,"appName":"appIntegrated6","status":"Pending"},"app7":{"id":7,"appName":"appIntegrated7","status":"Pending"},"app8":{"id":8,"appName":"appIntegrated8","status":"Pending"},"app9":{"id":9,"appName":"appIntegrated9","status":"Pending"},"app10":{"id":10,"appName":"appIntegrated10","status":"Pending"}};
$scope.currentPage = 0;
$scope.pageSize = 5;
$scope.totalPage = Math.ceil( Object.keys($scope.myJSONObj).length/$scope.pageSize);
//pageNumber starts from 0 here
$scope.goToPage = function(pageNumber) {
pageNumber = pageNumber>=0?pageNumber:0;
var from = pageNumber*$scope.pageSize;
var to = from + $scope.pageSize;
return Object.keys($scope.myJSONObj).slice(from,to).reduce(function(a,b){
a[b] = $scope.myJSONObj[b];
return a;
},{});
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="TestCtrl">
<button ng-disabled="currentPage===0" ng-click="currentPage = currentPage - 1">prev</button>
<button ng-disabled="currentPage===totalPage-1" ng-click="currentPage = currentPage + 1">next</button>
<b>Page: {{currentPage+1}}/{{totalPage}}</b>
<pre>{{goToPage(currentPage) | json}}</pre>
</div>

AngularJS filter already selected option from dynamic field

I have a form where you can add x number of fields. Each field contains option select. I want to filter out the already chosen option when this option is already chosen in one or multiples field before. Each field has a remove button and the form has 1 add button.
How can I filter out the dynamic fields?
Any help,guidance is most welcome.Thanks in advance. :)
This is how my HTML looks like:
<div data-ng-repeat="choice in choices">
<select data-ng-model="choice.option"
data-ng-options="item as item.Value for item in options">
</select>
<button data-ng-click="removeChoice(choice)">Remove choice</button>
<div>
<button data-ng-show="choices.length <= 4" data-ng-click="addNewChoice()">Add Choice</button>
</div>
</div>
And my controller:
$scope.options = [
{
"Key": "0",
"Value": "Select an option"
},
{
"Key": "Option1",
"Value": "Option1"
},
{
"Key": "Option2",
"Value": "Option2"
},
{
"Key": "Option3",
"Value": "Option3"
},
{
"Key": "Option4",
"Value": "Option4"
},
{
"Key": "Option5",
"Value": "Option5"
}
];
$scope.choices = [{ id: '1' }];
$scope.addNewChoice = function () {
var newItemNo = $scope.choices.length + 1;
$scope.choices.push({ id: newItemNo, option: $scope.option, value: $scope.value });
};
$scope.removeChoice = function () {
var index = $scope.choices.indexOf(choice);
$scope.choices.splice(index, 1);
};
ok
i can give simple recommendation which will be this.
1: add variable $scope.selectedOptions = [];
this will contain list of already selected options from all select elements .
2: create function $scope.AddSelectedOption(item);
this will add the selected object when we change option from any select element because we are going to use for all selects ng-change= "AddSelectedOption(item);"
3: add checkIfSelected(item); this will check if given object value is already selected or not ..
will user in
hope you understand what it will do just check like this
$scope.checkIfSelected = function (item) {
$scope.selectedFound = $scope.selectedOptions.filter(function
(option) {
if(option.value == item.value)
{
return day;
}
});
if($scope.selectedFound.length == 0 ) { return false; } else {
return true; }
}
This will return true if give item found in the options.
if not out.. you can invite me to help again .
This is possible. I'm explaining a basic version of this requirement. See the working example here http://plnkr.co/edit/S9yZpjhY55lXsuifnUAc?p=preview
What wer are doing is maintaining another options which is the copy of the original options. Copying the options will make it to not reference existing options since objects are pass by reference in Javascript.
The main logic is in this function, which modify the options on selection:
$scope.optionSelected = function(choice) {
$scope.availableOptions = $scope.availableOptions || angular.copy($scope.options);
if (choice.option) {
var index = -1;
// See if available options has that key
angular.forEach($scope.availableOptions, function(item, i) {
if (item.Key === choice.option.Key) {
index = i;
}
});
if (index > -1) {
// And then remove it
$scope.availableOptions.splice(index, 1);
}
}
};

Angular.js - How to make limitTo dynamic and persistant inside a nested ng-repeat with real time socket.io data updates

So I have an app that is updating data in real time using socket.io and displaying it with Angular JS.
I have it displaying data (comments) in multiple ng-repeats which are using ‘track by’ to ensure that duplicates are ignored when the latest data is brought in. I’m also using LimitTo to only show a certain amount of comments at a time, LimitTo is dynamic and is increased when the user clicks a button.
The HTML
<div ng-controller="CommentsController" >
<!-- Comment Repeater Starts Here -->
<div ng-repeat="comment in comments | limitTo: limit track by comment.id" >
{{ comment.comment }}
<!-- Nested Reply Comments Start Here -->
<div ng-repeat="reply in comment.replies | limitTo: comment.limit track by reply.id" >
<div class="comment-text" >
{{ reply.comment }}
</div>
</div>
<a href="#" ng-click="increaseReplyLimit(comment, comment.limit)" ng-show="hasMoreComments(comment.replies, comment.limit)" >View More Replies</a>
</div>
<a href="#" ng-click="increaseLimit(limit)" ng-show="hasMoreComments(comments,limit)" >View More Comments</a>
It works perfectly fine for my first ng-repeat, because I assign LimitTo to a variable on the scope, which is unaffected when I bring in new data through Socket.io. For my nested ng-repeat, though, I am using comment.limit as the variable for the LimitTo and this gets overwritten every single time I bring in the new data through socket.io.(the new data has a default for comment.limit - i tried leaving this blank before but then nothing shows).
The Angular
app.controller('CommentsController', function ($scope,socket,$http,$location) {
// fetching the latest comments from the API location
$http.get( $url + 'comments').success(function(comments) {
if (comments) {
$scope.comments = comments;
}
});
// updating comments via socket.io
socket.on('comment.update', function (data) {
$scope.comments = JSON.parse(data);
});
$scope.limit = 2;
$scope.hasMoreComments = function(comments, limit) {
if (typeof comments != "undefined" && comments != "false") {
var $commentLength = comments.length;
if ($commentLength > limit) {
return true;
}
return false;
}
return false;
}
$scope.increaseLimit = function(limit) {
$scope.limit = $scope.limit + 2;
}
$scope.increaseReplyLimit = function(comment, limit) {
comment.limit = parseInt(limit) + 2;
}
});
How can I prevent the current limit for each nested repeat from getting overwritten when I bring in new data from socket.io?
I already tried doing a deep merge on both the old and new data (with the idea of updating the nested limit in the new data to reflect the current nested limit). However, when i did that, Angular completely ignored the new limit and no longer enforced any limit for nested comments.
Structure of the data being brought in
[
{
"topics": [
{
"id": 75,
"topic": "test",
"approved": 1,
"created_at": "-0001-11-30 00:00:00",
"updated_at": "-0001-11-30 00:00:00",
"slug": "test",
"blurb": null
}
],
"id": 849,
"user_id": 80,
"news_id": 9,
"context": "Test News Article 1",
"comment": "<p>test comment 4</p>",
"origin": "Test",
"origin_url": "http://localhost:8000/news/test-news-article-1",
"author": "omurphy27",
"author_url": null,
"votes": 0,
"created_at": "2015-06-08 22:36:53",
"updated_at": "2015-06-08 22:36:53",
"approved": 1,
"slug": "test-comment-116",
"original": 1,
"parent_id": null,
"username": "omurphy27",
"limit": 2,
"voted": false
}
]
Been banging my head against the wall for awhile with this one and any help is much appreciated.
I ended up creating a separate array for my nested reply limits and attaching it to the scope (rather than having these limits in the data object that was being brought in and updated in realtime by socket.io )
See my updated angular code below
app.controller('CommentsController', function ($scope,socket,$http,$location) {
// fetching the latest comments from the API location
$http.get( $url + 'comments').success(function(comments) {
if (comments) {
$scope.comments = comments;
}
// populate my separate array for reply limits
$scope.populateLimits(comments.length, 4);
});
$scope.populateLimits = function(limitLength, limit) {
var limits = [];
for (var i = limitLength - 1; i >= 0; i--) {
limits[i] = limit;
};
$scope.limits = limits;
}
// updating comments via socket.io
socket.on('comment.update', function (data) {
if (data.length > $scope.comments.length) {
var difference = data.length - $scope.comments.length;
// increment the limits array by however
// many new comments are pulled in by socket.io
$scope.incrementLimits(difference);
}
$scope.comments = JSON.parse(data);
});
$scope.incrementLimits = function(difference) {
var newLimits = $scope.limits;
for (var i = 0; i < difference; i++) {
newLimits.unshift(2);
};
$scope.limits = newLimits;
}
$scope.limit = 2;
$scope.hasMoreComments = function(comments, limit) {
if (typeof comments != "undefined" && comments != "false") {
var $commentLength = comments.length;
if ($commentLength > limit) {
return true;
}
return false;
}
return false;
}
$scope.increaseLimit = function(limit) {
$scope.limit = $scope.limit + 2;
}
$scope.increaseReplyLimit = function(limit,index) {
$scope.limits[index] = parseInt(limit) + 2;
}
});
I populate this separate limits array based on how many 'parent' comments I have and then I increment it by however many new comments are brought in. Right now I'm just showing comments based in order, with the newest shown first, so I don't have to track which 'limits' belong to which comment; I can simply add new ones to the beginning of the array.
As for accessing the $scope.limits array in my nested ng-repeat and using it as the LimitTo variable, I do so using the following variable: limits[$index].
See my updated markup below:
<div ng-controller="CommentsController" >
<!-- Comment Repeater Starts Here -->
<div ng-repeat="comment in comments | limitTo: limit track by comment.id" >
{{ comment.comment }}
<!-- Nested Reply Comments Start Here -->
<div ng-repeat="reply in comment.replies | limitTo: limits[$index] track by reply.id" >
<div class="comment-text" >
{{ reply.comment }}
</div>
</div>
<a href="#" ng-click="increaseReplyLimit(limits[$index], $index)" ng-show="hasMoreComments(comment.replies, limits[$index])" >View More Replies</a>
</div>
<a href="#" ng-click="increaseLimit(limit)" ng-show="hasMoreComments(comments,limit)" >View More Comments</a>
</div>
The above fixes the issue I was having where the dynamic variable I was using for the limitTo for my nested ng-repeat kept getting overwritten. I do need to have the $scope.limits sync up better with my data, but I hope this helps anyone else who was encountering the same issue.
Cheers

How can I display one attribute of a set of data just once?

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.
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']);).
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>
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>
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>

Resources