Angular-Datatables wrong sorting on date - javascript

I'm using the angular-datatables plugin in my project, which works fine on all types, except for dates.
Example DESC:
01/01/2016
01/08/2015
01/08/2015
01/09/2015
Example ASC:
31/12/2015
31/10/2015
22/10/2015
I'm using the Angular Way with a date filter in my ng-repeat. I have a suspicion that it sorts with a wrong date format. I would like it to sort based on the day. How can I fix this?
<table class="table table-hover" datatable="ng">
<thead>
<tr>
<th>Client</th>
<th>Project</th>
<th>ID</th>
<th>Inv. Date</th>
<th>Start Date</th>
<th>End Date</th>
<th>DKK ex VAT</th>
<th>CIG</th>
<th>Attention</th>
<th>Cust. Manager</th>
<th>Regarding</th>
<th>Due Date</th>
<th>Finalized</th>
<th>Paid</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="invoice in vm.latestInvoices.LatestInvoices">
<td>{{invoice.CompanyName}}</td>
<td>{{invoice.ProjectName}}</td>
<td>{{invoice.InvoiceID}}</td>
<td>{{invoice.InvoiceDate | date: 'dd/MM/yyyy'}}</td>
<td>{{invoice.InvoiceStart | date: 'dd/MM/yyyy'}}</td>
<td>{{invoice.InvoiceEnd | date: 'dd/MM/yyyy'}}</td>
<td>{{invoice.DKKexVAT}}</td>
<td>{{invoice.CustomerInvoiceGroup}}</td>
<td>{{invoice.Attention}}</td>
<td>Customer Manager</td>
<td>{{invoice.Regarding}}</td>
<td>{{invoice.DueDate | date: 'dd/MM/yyyy'}}</td>
<td>No</td>
<td>{{invoice.Paid}}</td>
</tr>
</tbody>
</table>

dataTables generally does a good job by detecting datatypes for each column. However, if the type detection meets anything that conflicts with for example assumed numbers, the column is turned into default alpha sorting. I strongly believe this is the case here - if the rendered content meets the dd/MM/yyyy criteria 100%, then dataTables should automatically sort that column as date.
Luckily we can force the date datatype through the columns / columnDefs settings. Use for example DTColumnDefBuilder :
$scope.dtColumnDefs = [
DTColumnDefBuilder.newColumnDef([3,4,5,11]).withOption('type', 'date')
];
This forces column 3,4,5 and 11 to be of type date. Include dtColumnDefs in the markup :
<table class="table table-hover" datatable="ng" dt-column-defs="dtColumnDefs">
Example - try to comment out the .withOption('type', 'date') and see the difference -> http://plnkr.co/edit/XpBcLhlm0Frq3voN6X97?p=preview

Though it's late, but there is an alternative approach for those who want more flexibility.
You can solve the sorting problem in the way mentioned in the Ultimate Date / Time sorting plugin.
The code is really simple:
jQuery.fn.dataTable.moment('DD/MM/YYYY');
You can import the plugin from the datatable CDN:
<script src="https://cdn.datatables.net/plug-ins/1.10.13/sorting/datetime-moment.js"></script>
Note: You'll need to include momentJs in your application in order to use the plugin.

I solved this issue creating a filter
daterFilter.js
angular.module("app").filter("dateFilter", function(){
return function(input) {
var o = input.replace(/-/g, "/"); // Replaces hyphens with slashes if dd/mm/YYYY format
return Date.parse(o + " -0000");
};
});
In html file
<span>[[ ::created_at | dateFilter | date:"dd/MM/yyyy HH:mm"]]</span>
I saw this answer some time ago in this stack:
AngularJS: How to format ISO8601 date format?

this.dataSource.sortingDataAccessor = (item, property) => {
switch (property) {
case 'creationDate': return parse(item.creationDate, 'dd-MM-yyyy', new Date());
default: return item[property];
}
};
Add this on ngAfterViewInit method

Related

Rendering DB values using Javascript

Till date in a project of mine there has been straight forward implementation of DB normalization and the way "status codes" are stored , for example
Patient_table
patientId | referralStatus
1001 1
1002 2
Referral_status_codes_master
refStatusCode | refValue
1 Pending
2 Awaiting
Joining these two tables gives appropriate data for "STATUS_CODES" .
My intent here is , would it be appropriate if i use Javascript to achieve this for relatively small Master table values , i.e which don't change at all , like status here for example .
let's say i load patient data in a HTML table as it is and by using javascript i change their meanings .
<tr>
<td>1001</td>
<td>1</td>
</tr>
Objective : Intead of using join in sql query , obtain same results using Javascript on client side.
and i bind that HTML table to a JS function and change status 1 to "Pending", i know it's possible ,my Question is :
What are the disadvantages of doing it .
Are there any Libraries already existing for this very purpose only.
Please provide your suggestions .
Thank you
Since you have finite number of statuses, you can map values to user friendly name and than just replace them using js/jQuery
var statusMap = {
'1': 'Normal',
'2': 'Missing',
'3': 'Dead',
};
$(document).ready(function () {
$('[data-status]').each(function () {
$(this).html(statusMap[$(this).data('status')]);
})
});
table {
width: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<th>Name</th>
<th>Status</th>
</tr>
<tr>
<td>John Wick</td>
<td data-status="2"></td>
</tr>
<tr>
<td>Abraham Lincoln</td>
<td data-status="3"></td>
</tr>
<tr>
<td>Dummy User</td>
<td data-status="2"></td>
</tr>
</table>
statusMap can be generated from PHP side by doing json_encode({All values from Referral_status_codes_master});

Sorting with StupidTable JS and Date Columns

I am using StupidTable JS to sort my table columns. Works great. However most of my columns sort with
data-sort='string'
and now I have a DATE column I need to sort. Not sure how to do this. The info is fed from a database so I believe I need some function. The format each date is in is
dd-Mon-yyyy ex: 12-MAY-2015 or 25-JUL-2014
??
If you have control over the rendering of the HTML, you can sort on the timestamp while still displaying the pretty date.
https://github.com/joequery/Stupid-Table-Plugin#data-with-multiple-representationspredefined-order
Otherwise you'll need to create a custom sort function.
<table>
<thead>
<tr>
<th data-sort="string">Name</th>
<th data-sort="int">Birthday</th>
</tr>
</thead>
<tbody>
<tr>
<td>Joe McCullough</td>
<td data-sort-value="672537600">April 25, 1991</td>
</tr>
<tr>
<td>Clint Dempsey</td>
<td data-sort-value="416016000">March 9, 1983</td>
</tr>
...
You could sort by int after converting the date string to an time-stamp (integer).
From the Stupid-table docs:
The plugin internally recognizes "int", "string", "string-ins" (case-insensitive) and "float", so simple data tables will take very little effort on your part.
var dateString = '12-MAY-2015'
var date = new Date(dateString).getTime()
// 1431385200000
Then use data-sort='int' on your th elements.
Or you could use a custom function:
These data types will be sufficient for many simple tables. However, if you need different data types for sorting, you can easily create your own!
<th data-sort="date">Date</th>
var table = $("table").stupidtable({
"date": function(a,b){
// Get these into date objects for comparison.
aDate = new Date(a);
bDate = new Date(b);
return aDate - bDate;
}
});
Note: above code not tested
I had the same problem, and fixed it as follows:
<td><span style="display:none;">20150512</span>12-MAY-2015</td>
Like this in PHP:
<? php
$ date = date_create (YOUR_DATABASE_FIELD);
echo '<td><span style="display: none;">'. date_format ($ date, "Ymd"). '</span>'. date_format ($ date, "d-M-Y"). '</td>';
I hope this help you!

How to sort date and string in same column in jquery plugin having file jquery.dataTables.js?

I have a table containing "Date(in format M/d like 'Aug-23')" and string(like 'process' and 'completed') in same column. But the issue is that it is sorted alphabetically not sort according to Date.
And structure of my file is:
<script type="text/javascript" language="javascript" src="../../table-sorting/js/jquery.js"></script>
<script type="text/javascript" language="javascript" src="../../table-sorting/js/jquery.dataTables.js"></script>
<script type="text/javascript" language="javascript" class="init">
$(document).ready(function() {
$('#sorting').dataTable( {
"dom": '<"top"iflp<"clear">>rt<"bottom"iflp<"clear">>'
} );
} );
</script>
CPA Shipping
123 Aug-28
327 July-30
789 Process
if i sort shipping column then it give result like
Process
Aug-28
July-30
But i want result like:
Process
July-30
Aug-28
means firstly string sorting and after that date sorting
And these shipping values are coming from Mysql database
How I solve this issue??
Any Suggestion??
You have to write your dates in YYYYmmdd format so that alphabetical order matches chronological order.
But you want your dates to be displayed in a better-looking format (legit).
The solution is to have 2 columns: one with the good-looking date, one with the YYYYmmdd date. This one will be hidden, but will be used by dataTable sorting function.
<table id="sorting">
<thead>
<tr>
<th>CPA</th>
<th>Shipping</th>
<th>Shipping (sorting format)</th>
</tr>
</thead>
<tbody>
<tr>
<td>123</td>
<td>Aug 28</td>
<td>20150828</td>
</tr>
<tr>
<td>327</td>
<td>July 30</td>
<td>20150730</td>
</tr>
<tr>
<td>789</td>
<td>Process</td>
<td>0</td>
</tr>
</tbody>
</table>
Then, the Javascript :
$('#sorting').dataTable( {
"aoColumns": [
{"bSortable": true}, // First column: normal
{"iDataSort": 2}, // Second column's sorting depends on third column (dataTable starts counting from 0, that's why third column is number 2)
{"bVisible": false}, // Third column: hide it
]
});
You'll find more tips and examples in DataTables' documentation.

Changing or editings Keys in objects, in order to show in view. Using Angular

Example JSON:
[{"name":"John", "date_of_birth":"01/12/1987","marital_status": "Open Relationship"}]
Example view:
<table>
<tr>
<th> Name </th>
<th>Date of Birth</th>
<th>Martial Status</th>
</tr>
<tr ng-repeat= "profile in profiles">
<td>{{profile.name}}</td>
<td>{{profile.date_of_birth}}</td>
<td>{{profile.marital_status}}</td>
</tr>
</table>
What I want is to ng-repeat the keys or table heading too. I know how to put ng-repeat and get keys and values. But what I will like is to change the keys and make them look nice, for e.g : date_of_birth should be Date of Birth, but with ng-repeat on it.
I do agree with the comments in under your question that it is not the best approach. Also, remember that in reality you shouldn't count on a particular order when iterating over object's params (see https://github.com/angular/angular.js/issues/6210).
However ;) in the spirit of solving interesting question…
If you really want to do this, you can do it this way:
<table>
<tr ng-repeat="(key, value) in profiles[0]">
<th>{{ key | snailToHuman }}</th>
</tr>
<tr ng-repeat= "profile in profiles">
<td>{{profile.name}}</td>
<td>{{profile.date_of_birth}}</td>
<td>{{profile.martial_status}}</td>
</tr>
</table>
And create a filter snailToHuman, e.g.:
app.filter('snailToHuman', function () {
return function (snail) {
return snail.split('_').map(function (word) {
word.charAt(0).toUpperCase() + word.slice(1);
}).join(' ');
};
})

Forcesorting, then disabling sort using jQuery Tablesorter

I have this table that I am sorting with tablsorter. I want to force sort the C, but I also want to make that row not clickable by the user. (meaning tablesorter force sorts on this row, then the user can't touch it.)
<table>
<thead>
<tr>
<th>A</th>
<th>B</th>
<th>C</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</tbody>
</table>
Here is my tablesorter code:
params = {
sortList: [[2, 0]]
, headers: {
0: { sorter: false },
1: { sorter: 'text' },
2: { sorter: 'text' },
}
}
, sortForce: [[2,0]]
};
When i set row 2 to : 2: { sorter: false }, I get an exception. I think this exception is because my sortList is set to [[2,0]], my sortFroce is set to [[2,0]], but setting row 2 to, 'false'. --Is there a way to do this?
I seem to remember an issue with sortForce not working correctly, but I can't seem to find it in the change log, except back in version 2.0.2.
Either way, it should be fixed in my fork of tablesorter on github. Here is a demo I put together (I left out the sortList option so you can see the last column sort.

Categories

Resources