using part of a list in angularJS ng-repeat - angularjs

I'm doing an angularJS data-binding as follows:
<div class="timeSlotWrapper">
<div class="timeSlotItem" ng-repeat="t in timeSlots" time-slot-obj="t" id ="{{t.id}}"
ng-click="timeSlotClick(cardId, $index)">{{ t.signalingTimeSlot}}</div>
</div>
the collection timeslots contain some 60 items, 30 of each belonging to one category. Lets say typeId is 0 for 30, and 1 for the other 30. I want to use ng-repeat for the first 30 only. Is it possible to do within ng-repeat or do I have to create the collection according to my need in code behind?

<div class="timeSlotWrapper">
<div class="timeSlotItem" ng-repeat="t in timeSlots | filter:{typeId:0}" time-slot-obj="t" id ="{{t.id}}"
ng-click="timeSlotClick(cardId, $index)">{{ t.signalingTimeSlot}}</div>
</div>

You can make use of angular filter. Example for same
myApp.filter('filterList', function () {
return function(id) {
if(id==1)
return id;
}
});
And in your html markup
<div class="timeSlotItem" ng-repeat="t in timeSlots | filterList:t.id" time-slot-obj="t" id ="{{t.id}}"
ng-click="timeSlotClick(cardId, $index)">{{ t.signalingTimeSlot}}</div>
UPDATE:
If 1 need not be hardcoded then a $scope object can be used in the filter:
myApp.filter('filterList', function () {
return function($scope) {
$scope.Objs.forEach(function(Obj){
if(id==$scope.Obj.id) {
return id;
}
});
}
});
and in html markup pass this object
<div class="timeSlotItem" ng-repeat="t in timeSlots | filterList:this" time-slot-obj="t" id ="{{t.id}}"
ng-click="timeSlotClick(cardId, $index)">{{ t.signalingTimeSlot}}</div>
Documentation on Angular Filters

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 ng-repeat output groupBy value

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>

How can I limit rows showing in an ng-repeat?

I have an ng-repeat that looks like this:
<div ng-repeat="subject in subjects">
<div>{{ subject.name }}</div>
</div>
Is there some way that I can limit the display of rows to rows where subject.id is less than 50 if roleId > 1 and otherwise show all rows?
$scope.roleId = 0 means no filter
$scope.roleId > 0 means filter to show only rows in $scope.subjects where subject.id is less than 50
You can accomplish this using ng-if or use a filter
<div ng-repeat="subject in subjects" ng-if="subject.id>50">
The part about the role id in question is not clear
Use Limit to Filter
<div ng-repeat="subject in subjects | limitTo:quantity">
<div>{{ subject.name }}</div>
</div>
then set the $scope.quantity in your controller based on your business logic.
Use a Custom Filter
to use a custom filter you just set a new $scope function in your controller.
$scope.yourFilter = function (items) {
// probably need some more logic but you get the idea
return items.id < 50;
};
thin in the filter it should look like this
<div ng-repeat="subject in subjects | filter:yourFilter(subjects)">
<div>{{ subject.name }}</div>
</div>
Add a filter
<div ng-repeat="subject in subjects | filter:filterFn">
<div>{{ subject.name }}</div>
</div>
And in your controller, have this function:
$scope.filterFn = function (item) {
if ($scope.roleId > 1) {
return (item.Id < 50) ? true : false;
}
else
return true;
};
If I understood your comments correctly.

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;
}

jQuery UI Sortable with AngularJS Multiple Columns

While using jQuery UI Sortable (multiple columns) I want to save the dropped item data which is a json object into an existing array, so I can have a live update for the view. The problem is when I log $('.selector').sortable('toArray') within 'sortupdate' it always returns 2 arrays. I want to splice the dropped item data like this $scope.items.splice(index, 1, newData). As the sortable returns 2 arrays, I cannot find the right index of the dropped item in the array. In HTML I have something like this:
<div id="ticket-{{status | lowercase | removeWhiteSpace}}" class="col-xs-12 col-sm-6 col-md-4 col-lg-3" data-ng-repeat="status in ticketStatus">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title white-text-shadow ticket-{{status | lowercase | removeWhiteSpace}}">{{status}}</h4>
</div>
<div class="panel-body overview-thumb-container" id="ticket-panel-{{$index}}">
<div data-ng-class="getBorderClass(item.deadline)" class="panel panel-default overview-thumbnail ngRepeatAnimation" id="item-{{item.id}}" data-ng-repeat="item in items | filter: searchItem | filter: {status: status}:true | orderBy:'id':true">
<div class="panel-heading">
<h6 class="panel-title">
<a data-ng-href="#/item/{{item.id}}" data-ng-click="viewItemDetail()" data-tooltip="{{item.title}}" data-tooltip-placement="bottom">{{item.title | limitTo: 30}}</a>
</h6>
</div>
<div class="panel-body">{{item.description | limitTo: 80}}</div>
<div class="panel-footer white-text-shadow">
<div class="pull-left time" data-ng-class="getTextClass(item.deadline)">{{item.deadline | limitTo: 10}}</div>
<div class="pull-right text-right link">
<ul class="list-inline">
<li><a data-ng-href="#/item" data-ng-click='deleteItem(item.id)'><i class="fa fa-trash-o"></i></a></li>
<li><a data-ng-href="#/item/{{item.id}}" data-ng-click="viewIssueDetail()">Details</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
In Controller:
app.controller('TicketCrtrl', function($scope, $http, $timeout, TicketService) {
// this service is defined
TicketService.getData().then(function(tickets) {
$scope.items = tickets;
dnd();
});
function dnd() {
var container = angular.element('.overview-thumb-container');
container.sortable({
placeholder: "ui-state-highlight",
opacity: 0.6,
cursor: 'move',
connectWith: '.overview-thumb-container'
});
var from, to,
id = -1,
index = -1,
currentData = new Object();
container.on('sortstart', function(e, ui) {
from = $(e.target).parent().find('h4').text();
var cid = $(ui.item).attr('id'); // current dragged item id
id = parseInt( cid.substr(cid.lastIndexOf('-') + 1) );
angular.forEach($scope.items, function(item, key) {
if (item.id === id) {
index = key;
angular.extend(currentData, item);
return;
}
});
});
container.on('sortstop', function(e, ui) {
to = ui.item.parent().parent().find('h4').text();
// dropped in a different column
if ( from !== to ) {
// remove the status attribute from current object
delete currentData.status;
// extend the new status to this data
angular.extend(currentData, {'status': to});
} else
return; // dropped in the same column
});
container.on('sortupdate', function(e, ui) {
console.log($(this).sortable('toArray')); // it returns 2 arrays with item ids
// update this data
$http.put(root.path + '/' + id, currentData).success(function() {
ui.item.animate({backgroundColor: '#f5fff5', borderColor: '#239169'}, 300).animate({backgroundColor: '', borderColor: '#ddd'}, 200);
$timeout(function() {
// replace the old data with the new one
$scope.items.splice(index, 1, currentData); // this doesn't work as the indexs are changed. It causes duplicates in ng-repeat
}, 500);
}).error(function(data, status) {
root.showHideWarningInfo($scope.errorConnectServer + status);
// put item back to its original position
container.sortable('cancel');
});
});
};
}
The array looks like this;
[{"description":"test 01","title":"test 01","deadline":"05/19/2014 00:00","status":"normal","id":1},{"description":"test 02","title":"test 02","deadline":"05/19/2014 00:00","status":"high","id":2},{"description":"test 03","title":"test 03","deadline":"05/20/2014 00:00","status":"low","id":3}]
Could someone help, how I can find the right index of the dropped item in the array, so the view can be updated. Thanks in advance.
The AngularUI Sortable directive's Github page, under the 'Developing Notes' header, suggests that the:
ui-sortable element should only contain one ng-repeat and not any other elements (above or below).
Otherwise the index matching of the generated DOM elements and the ng-model's items will break.
In other words: The items of ng-model must match the indexes of the generated DOM elements.
You may either 1. want to use the AngularUI Sortable directive, or 2. call 'sortupdate' on the same element that contains the ng-repeat, rather than on its container div, to see if that causes the ng-repeat $index to match the indexes of the generated DOM elements.

Resources