Say I have this piece of code:
<tr ng-repeat-start="caseHistory in vm.caseHistory">
<td >{{caseHistory.date | date:"dd-MMM-yyyy h:mm a"}}</td>
<td >{{caseHistory.description}}</td>
<td >{{caseHistory.performedByUser.firstName}} {{caseHistory.performedByUser.lastName}} ({{caseHistory.performedByUser.externalAssociateId}})</td>
<td>
<span ng-show="vm.showCreateCaseComments(caseHistory.eventType,caseHistory.comments)">
<a ng-if="caseHistory.expanded" class="removeTextDecoration headerPointer" ng-click="caseHistory.expanded = false"> -Collapse</a>
<a ng-if="!caseHistory.expanded" class="removeTextDecoration headerPointer" ng-click="caseHistory.expanded = true"> +Expand</a>
</span>
</td>
</tr>
I would like it so that everything that is shown to be sorted by ascending chronological date.
What would I need to add in {{caseHistory.date | date:"dd-MMM-yyyy h:mm a"}} in order to sort all the results in by the date?
You need to add a pipe here:
<tr ng-repeat-start="caseHistory in vm.caseHistory | orderBy:'caseHistory.date'">
You could also add the '-' symbol to specify ascending vs descending.
Documentation can be found here:
https://docs.angularjs.org/api/ng/filter/orderBy
Use orderBy filter and add the reverse option for descending
<tr ng-repeat-start="caseHistory in vm.caseHistory | orderBy: 'date':true">
Or add a - in front of field name
<tr ng-repeat-start="caseHistory in vm.caseHistory | orderBy: '-date'">
According to Angular Official Tutorial pipe or filter should not be used for sorting purpose.
You can write your custom method to perform this task like :
Main.prototype = {
sort: function(item) {
if (this.predicate == 'date') {
return new Date(item.date);
}
return item[this.predicate];
},
sortBy: function(field) {
if (this.predicate != field) {
this.predicate = field;
this.reverse = false;
} else {
this.reverse = !this.reverse;
}
},
reverse: false};
Please refer following jsfiddle for reference.
Related
Trying to loop over an array and display the results, but only the last element showing multiple times.
Here is my code.
Making a get request.
showItems(id: any): Observable<any> {
return this.http.get(`${this.url}${id}`)
}
Console logging works fine here, I can see the expected results.
ngAfterViewInit(): void {
this.showItems()
}
showItems(): void {
const id: any = []
this.idFromList.forEach((val: any) => id.push(val.nativeElement.innerText))
for(let i = 0; id.length > i; i++) {
this.ItemService.showItems(id[i]).subscribe(data => {this.api_items = data.item.current
console.log(this.api_items)});
}
}
HTML
<table>
<thead>
<tr>
<td>Name</td>
<td>Price</td>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of items | filter: searchQuery" >
<td >
<a href="" #btn>{{item.id}}</a>
{{ item.name }}
</td>
<td *ngFor="let api_item of api_items | keyvalue">
{{ api_item.value }}
</td>
</tr>
</tbody>
</table>
Tried using fake JSON server, same results.
1) Quick answer
Push items in an array instead of replacing its value :
api_items = [];
this.ItemService.showItems(id[i]).subscribe(data => {
this.api_items.push(data.item.current);
});
2) Complete answer
As #MoxxiManagarm said, you're replacing api_items value at each iteration of your for loop.
You might want to check & use RxJS to handle multiple observables in a cleaner way: for example, by generating an array of Observable to resolve them together.
3) Ressources & useful links you might want to check for more information
https://www.learnrxjs.io/
I am currently using the on-click sort functionality on my table & is working fine. But now I also need to sort my table in descending order of dateCol on page load. So that, initially the table would be sorted in descending order of dateCol column & if we click on column header, the appropriate sort should also work.
Here's my code -
$scope.sort = function(keyname){
if($scope.ref.displayTxnList && $scope.ref.displayTxnList.length > 0)
if(checkDuplicateInObject(keyname,$scope.ref.displayTxnList) > 1)
{
if ($scope.sortKey == keyname) {
$scope.reverse = !$scope.reverse;
} else {
$scope.sortKey = keyname;
$scope.reverse = false;
}
}
$scope.currentPage = 1;
}
And the snippet is -
<table class="table table-hover table-standard">
<thead>
<th ng-click="sort('dateCol')"></th>
</thead>
<tbody>
<tr ng-repeat="t in ref.displayTxnList | orderBy:sortKey:reverse | startFrom:( currentPage - 1 ) * pageSize | limitTo: pageSize track by $index">
...
</tr>
</tbody>
</table>
According to the documentation, we can provide multiple arguments to orderBy as - | orderBy : expression : reverse : comparator. So, making use of the same, we can use one more orderBy as follows -
<tr ng-repeat="t in ref.displayTxnList | orderBy:'dateCol':false | orderBy:sortKey:reverse | startFrom:( currentPage - 1 ) * pageSize | limitTo: pageSize track by $index">
...
</tr>
Where, I've provided reverse as false, which gives me a descending order.
<table>
<thead>
<tr>
<th class="col-md-3" ng-click="sortDirection = !sortDirection">Created At</th>
</tr>
</thead>
<tbody>
<tr dir-paginate="food in foods | filter:foodFilter | itemsPerPage:pageSize | orderBy:'created_at_date'">
<td class="col-md-"> {{food.created_at_date}} </td>
</tbody>
</table>
<dir-pagination-controls
max-size= 7
boundary-links="true">
</dir-pagination-controls>
This is only a snippet of my code but its too large to put up. Everything is working except only some of the created_at_date is in order. When I click on a different filter to add in or remove data depending on that filter, only some of it is entered into the correct place. My main question is: is there someway to sort all of the dates properly while still allowing the everything else function as well? All help is welcome, Thanks
(function () {
"use strict";
App.controller('foodsController', ['$scope'],
function($scope) {
$scope.sortDirection = true;
In your controller you can add the method to order the array before you loop over them.
Assuming your foods array has an array of objects, each with a key of created_at_date and a value:
App.controller('foodsController', function($scope) {
$scope.foods = [{
created_at_date: 6791234
}, {
created_at_date: 9837245
}, {
created_at_date: 1234755
}];
// create a method exposed to the scope for your template.
$scope.orderBy = function(key, array) {
// now you've received the array, you can sort it on the key in question.
var sorted = array.sort(function(a, b) {
return a[key] - b[key];
});
return sorted;
}
});
Now on your template, you have a method available to sort your values for you:
<table>
<thead>
<tr>
<th class="col-md-3" ng-click="sortDirection = !sortDirection">Created At</th>
</tr>
</thead>
<tbody>
<tr dir-paginate="food in orderBy('created_at_date', foods) | filter:foodFilter | itemsPerPage:pageSize">
<td class="col-md-"> {{food.created_at_date}} </td>
</tr>
</tbody>
</table>
The orderBy method which we've created on your controller returns an array, but it's just sorted by the key that's sent in as the first argument of the function. The second argument is the original array you're trying to sort.
At least this way you can check if you remove all your other filters to see if it's ordered correctly, if then after you add them back in it changes it's because those filters are also changing the order.
I use angularjs in my project.
I want to filter my array in ng-repeat.
Here is HTML:
<tbody>
<tr ng-repeat="sensorData in list.sensorsData |
filterByAlert:list.alertTags">
<td>
<div class="container-fluid">
<div class="row">
<div class="text-center">{{ sensorData.Area }}</div>
</div>
</div>
</td>
</tr>
</tbody>
Here is how looks list.sensorsData array of objects:
Here is how looks list.alertTags array of objects:
I need to show in ng-repeat elements only list.sensorsData rows that has alertType properties value equal to Id proiperty in list.alertTags.
for this purpose I wrote this filter:
(function () {
"use strict";
angular.module("sensorsData").filter('filterByAlert', filterByAlert);
function filterByAlert() {
var result = [];
return function (sensorRecords, alertTypes) {
if (!sensorRecords)
return;
if (!alertTypes)
return;
angular.forEach(sensorRecords, function (sensorRecord, key) {
angular.forEach(alertTypes, function (alertType, key2) {
if (sensorRecord.AlertType == alertType.Id ) {
result.push(sensorRecord);
}
})
});
return result;
}
};
})();
but when filter is fired I get this error:
angular.js:13424 Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: sensorData in list.sensorsData |
filter:filterByAddress |
orderBy:sortType:sortReverse |
filterByAlert:list.alertTags, Duplicate key: object:8, Duplicate value: {"Id":8,"Address":"125 king g.str","AlertType":3,"Area":"North","MeasureDate":"2012-10-12T16:10:00","MeasureValue":-1}
It seems I have problem with logic in my custom filter.
Any idea why I get the error?And how to fix it?
Add track by $index to your ng-repeat.
<tr ng-repeat="sensorData in list.sensorsData | filterByAlert:list.alertTags track by $index">
I'm just getting started with AngularJS and I'm trying to sort my table so that when a tableheader is clicked the rows are sorted per that table header.
Here is my plnkr link:
http://plnkr.co/edit/mbTq5865KKNzlvpJJy1l
Here is my relevant code:
Controller code:
$scope.setRepoSortOrder = function(order) {
if ($scope.repoSortOrder === order) {
if ($scope.repoSortOrder.charAt(0) === '+') {
order = order.replace('+', '-');
} else {
order = order.replace('-', '+');
}
}
$scope.repoSortOrder = order;
};
Table:
<table>
<thead>
<tr>
<th>Name</th>
<th>Stars</th>
<th>Language</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="repo in repos | orderBy:repoSortOrder">
<td>{{repo.name}}</td>
<td>{{repo.stargazers_count | number}}</td>
<td>{{repo.language}}</td>
</tr>
</tbody>
</table>
So when the name th is clicked the rows should be sorted by the names - same with stargazers_count and language. If a th is clicked again it should be sorted in the opposite order (if I click name first it's sorted by names in asc order - if I click it again it's sorted in desc order).
Finally: name and language should initially sort in asc order while stargazers_count should sort in desc order initially.
I've done this myself but I don't know if I'm doing it the best way possible. Since I'm not used to the "angular style" I would like to hear how people familiar with AngularJS would handle this. Please check out the plnkr link to see if you could improve it.
Any replies are appreciated!
One thing that can improve is to use a reverse flag of the orderBy filter like this:
$scope.repoSortOrder = "-stargazers_count";
$scope.isReverse = false;
$scope.setRepoSortOrder = function(order) {
$scope.isReverse = ($scope.repoSortOrder === order) ? !$scope.isReverse : false;
$scope.repoSortOrder = order;
};
Example Plunker: http://plnkr.co/edit/CM1BGkQc0AYbrraAPq8r?p=preview