Angular ng-repeat output groupBy value - angularjs

I have this AngularJS repeater where i group my items by a property.
Data:
items = {
Load: 0,
Unit: 0,
object: {
Property: "prop"
}
}
Repeater
<div class="horizontalList">
<ul ng-repeat="(index, item) in vm.items | groupBy: 'object.Property' | toArray: true">
<div>GET OBJECT PROPERTY HERE</div>
<li ng-repeat="item in item | orderBy:'index'">
<div ng-bind="item.Load"></div>
<div ng-bind="item.unit"></div>
</li>
</ul>
</div>
It works fine, except i cannot output the value of object.Name, I've tried various things like:
<div ng-model="Item.object"></div>
<div ng-model="item.object.Name"></div>
<div ng-model="vm.items[index].object.property"></div>

Related

Grabbing value from nested json array with Angular

I'm having trouble accessing the artists array within the items array here to be able to render the name field:
I'm currently able to grab other values at the same level as the artists that are simple objects. How can I loop through the array of the nested array?
Controller
$scope.search = "";
$scope.listLimit = "10";
$scope.selectedSongs = [];
$scope.addItem = function(song){
$scope.selectedSongs.push(song);
}
function fetch() {
$http.get("https://api.spotify.com/v1/search?q=" + $scope.search + "&type=track&limit=50")
.then(function(response) {
console.log(response.data.tracks.items);
$scope.isTheDataLoaded = true;
$scope.details = response.data.tracks.items;
});
}
Template
<div class="col-md-4">
<div class="playlist">
<h3>Top 10 Playlist</h3>
<ul class="songs" ng-repeat="song in selectedSongs track by $index | limitTo: listLimit">
<li><b>{{song.name}}</b></li>
<li>{{song.artists.name}}</li>
<li contenteditable='true'>Click to add note</li>
<li contenteditable='true'>Click to add url for image</li>
</ul>
<div id="result"></div>
</div>
</div>
You should do another ng-repeat to access the artists,
<div class="songs" ng-repeat="song in selectedSongs track by $index | limitTo: listLimit">
<ul ng-repeat="artist in song.artists">
<li><b>{{song.name}}</b></li>
<li>{{artist.name}}</li>
<li contenteditable='true'>Click to add note</li>
<li contenteditable='true'>Click to add url for image</li>
</ul>
</div>

Angular expression in ng-repeat and ng-click

I am trying to call a function using ng-click which is dynamically generated by ng-repeat the problem is that i am not able to get the parameter value passed in ng-click function. My html code is
<div class="col-md-4 col-xs-12 col-lg-4" ng-repeat="(key, value) in uploadedFiles">
<b>value.filename is {{value.filename}}</b>
<img ng-if="value.filetype=='jpg'" ng-src="http://localhost:3000/uploads/{{value.filename}}" class="img img-responsive thumbnail uploadedfile-thumb"/>
<img ng-if="value.filetype=='PDF'" ng-src="images/pdf-thumb.jpg" class="img img-responsive thumbnail uploadedfile-thumb"/>
<a ng-href="http://localhost:3000/uploads/{{value.filename}}" target="_blank" class="uploaded-file-links">View</a>
<a ng-href="#" ng-click="deleteFile(value.filename);" class="uploaded-file-links">Delete</a>
</div>
i am not getting the filename which is passed in deleteFile(), bit it is working in <b> tag in 2nd line so finally this is a problem with my angular expression so how should i write it?
I will try to make some guessing here.
I suppose that your uploadedFiles is an array of objecs, and not an object itself. In that case, you should use ng-repeat="file in uploadedFiles" which is meant to iterate over array elements. This will iterate over your array and assignf the corresponding object for that iteration to file variable.
The ng-repeat="(key, value) in uploadedFiles" is meant for iterating over object properties instead of iterating over array elements. For example, if uploadedFiles is:
var uploadedFiles = {
prop1: 'value1',
prop2: 'value2',
prop3: 'value3'
};
and you iterate over it like this:
<ul>
<li ng-repeat="(key, value) in uploadedFiles">
{{value}}
</li>
</ul>
you would get the following output:
value1
value2
value3
But if uploadedFiles is an array like this one:
var uploadedFiles = [
{
prop1: 'value11',
prop2: 'value12',
},
{
prop1: 'value21',
prop2: 'value22',
},
{
prop1: 'value31',
prop2: 'value32',
}
];
And you iterate over it like this:
<ul>
<li ng-repeat="file in uploadedFiles">
{{file.prop1}}
</li>
</ul>
you would get:
value11
value21
value31
So in your case, I would try the following:
<div class="col-md-4 col-xs-12 col-lg-4" ng-repeat="file in uploadedFiles">
<b>file.filename is {{file.filename}}</b>
<img ng-if="file.filetype=='jpg'" ng-src="http://localhost:3000/uploads/{{file.filename}}" class="img img-responsive thumbnail uploadedfile-thumb"/>
<img ng-if="file.filetype=='PDF'" ng-src="images/pdf-thumb.jpg" class="img img-responsive thumbnail uploadedfile-thumb"/>
<a ng-href="http://localhost:3000/uploads/{{file.filename}}" target="_blank" class="uploaded-file-links">View</a>
<a ng-href="#" ng-click="deleteFile(file.filename);" class="uploaded-file-links">Delete</a>
</div>

How to use ng-repeat to display according to starting letter of item values

I have an array with items names ranging from A-Z.
What I want to do is ng-repeat for each letter of the alphabet.
For A letters in Array:
<div ng-repeat="item in items | orderBy: 'item_name'">
{{item.item_name}}
</div>
For B letters in Array:
<div ng-repeat="item in items | orderBy: 'item_name'">
{{item.item_name}}
</div>
How can I achieve this?
You can achieve this with custom filter
<div ng-repeat="item in items | filter:criteriaMatch('z')">
{{item.name}}
</div>
<div ng-repeat="item in items | filter:criteriaMatch('A')">
{{item.name}}
</div>
and filter function like below
$scope.criteriaMatch = function(x) {
return function( item ) {
return item.name.startsWith(x);
};
};
here is Working fiddle
hope it helps you :)
You can use the groupBy filter using the angular.filter module:
<div ng-repeat="item in items | groupBy: 'item_name.substr(0,1)'">
{{item.item_name}}
</div>

Filtering and grouping with angularJS group count

Given the following data:
[
{"Id": 3, "Name":"Image1.jpg", "AssetType":0, "Grouping": {"GroupingId": 4, "Name":"Other"}},
{"Id": 7, "Name":"Document1.jpg", "AssetType":2, "Grouping": {"GroupingId": 4, "Name":"Other"}},
{"Id": 8, "Name":"Video1.jpg", "AssetType":1, "Grouping": {"GroupingId": 4, "Name":"Other"}},
{"Id": 6, "Name":"Image2.jpg", "AssetType":0, "Grouping": {"GroupingId": 1, "Name":"Facebook"}},
]
I wanted to list separate groups of assets types, so I used the following ng-repeat:
<div class="group" ng-repeat="asset in assets | filterBy : ['AssetType'] : 0 "
<b>{{ asset.Grouping.Name}}</b><br />
{{ asset.Name }}
</div>
This gets me the following:
Other
Image1.jpg
Facebook
Image2.jpg
Now, I wanted to group by the grouping name, to test if there was only one group for this asset type. If there was only one, I was not going to show the grouping name, so I added a group by to the ng-repeat statement:
<div class="group" ng-repeat="(key, value) in assets | filterBy : ['AssetType'] : 0 | groupBy : 'Grouping.Name' ">
<b>{{ key }}</b> - {{ numGroups(key) }}<br />
<div ng-repeat="asset in value ">
{{ asset.Name }}
</div>
</div>
But when I added a function to get the count of keys for this filtered group, I got something unexpected:
Other - 5
Image1.jpg
Facebook - 8
Image2.jpg
numGroups is defined like this:
$scope.numGroups = function (key) {
return Object.keys(key).length;
}
I was expecting the length of keys to be 2 (Other and Facebook) but instead it looks like it is iterating all the items of the array.
Is there any way to get the count of group keys after a filter has been applied?
There is a way!
Here's how the solution worked out:
$scope.numGroups = function (map) {
var count = 0;
angular.forEach(map, function () { count++; });
return count;
}
and the Html
<div class="group" ng-repeat="(key, value) in images = (assets | filterBy : ['AssetType'] : 0 | groupBy: 'Grouping.Name') ">
<div class="groupName" ng-hide="numGroups(images) == 1"><b>{{ key }}</b></div>
<div ng-repeat="asset in value">
{{ asset.Name }} - Brand {{ asset.Brand.Name }}
</div>
</div>
In your function 'numGroups' you are getting the length of the 'Grouping.Name' String, it could be fixed if you use this:
<div class="group" ng-repeat="(key, value) in grouped = (assets | groupBy : 'Grouping.Name') ">
<b>{{key}}</b> - {{numGroups(grouped)}} <br />
<div ng-repeat="asset in value">
{{ asset.Name}}
</div>
</div>
And a tricky way of your noumGroups function:
$scope.numGroups = function(map){
var count = 0;
angular.forEach(map, function(){
count++;
})
return count;
}

Angular.js interpolation in filter parameter

I have a filter on a ng-repeat, which accepts a parameter. It currently works with a string.
<div ng-repeat="(key, value) in searchData | aboutFilter:'abo'">
Is is possible to use an interpolated value in place of the string?
<div ng-repeat="(key, value) in searchData | aboutFilter:'{{list.api}}'">
Here is my filter:
app.filter('aboutFilter', function() {
return function(items, input) {
var filtered = [];
angular.forEach(items, function (value,key) {
if(key===input){
filtered.push(value);
}
});
return filtered;
}
});
Here is the complete template logic:
<ul ng-repeat="list in englishList">
<a ng-class="{{list.title}}Hide" mobile-search-slide href="/about"><li><p>{{list.title}}</p><i class="fa fa-chevron-right"></i></li></a>
<ul id="hideMe" ng-class="'hide{{list.title}}'">
<div ng-cloak ng-repeat="(key, value) in searchData | aboutFilter:'{{list.api}}'">
<div ng-repeat="result in value" ng-class-odd="'odd'" ng-class-even="'even'">
<a ng-href="{{value.title}}/{{result.shortname}}">
<li>
<p>{{result.title}}</p><i class="fa fa-chevron-right"></i>
</li>
</a>
</div>
</div>
</li>
</ul>
</ul>
If you want to use some ng-modelfor filter, then you can just use the model name. No need to use {{}} expression.
In your case, it will be :
<div ng-cloak ng-repeat="(key, value) in searchData | aboutFilter:list.api">
DEMO
Remember in your filter, you are using string comparison. So the filter will check for exact matches.
And also, IN your filter:
You are comparing key with the input list.api. Here key will always be 0,1, etc index. You must be using value there instead of key

Resources