Sorting with StupidTable JS and Date Columns - javascript

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!

Related

How can I split the following string into an array that I can use to populate a html table

I have a string that looks like:
var str = '{ "abc": {
"decline_reason": "Business rule switched off"
},
"def": {
"decline_reason": "No response by interface"
},
"ghi": {
"decline_reason": "Requested incorrect size" }';
I would like to split that string into an array that I can use to populate a table on a webpage. I intend to use the initial reference ('abc'), with the reason ('Business rule switched off') on row 1, initial reference ('def'), with the reason ('No response by interface') on row 2, etc...
I have tried regex to break it down, and I've managed to find one that removes quotes, but not to break the string down.
I intend to populate the table with code like:
<table id="declinesTable">
<tr>
<th onclick="sortTable(0)">Reference Code</th>
<th>Decline Reason</th>
</tr>
<tr id="lender1">
<td id="lender1"><script>document.getElementById("lender1").innerHTML = declines[0];</script>
</td>
<td id="declineReason1"><script>document.getElementById("declineReason1").innerHTML = declines[2];</script>
</td>
</tr>
</table>
skipping out the value "decline_reason" from the table.
Any suggestions?
Couple of things - your string is missing a final }. Not sure where you're getting the string from, but it's in JSON format, so use JSON.parse to get it into an object, then iterate over the object to do something with each individual nested object. I would strongly recommend using a library like jQuery to help you append it to the table. You can google and very quickly find out how to add jQuery to your project. See below.
function stringParse(str) {
const json = JSON.parse(str);
const html = Object.entries(json).reduce((h, [k, v]) =>
h += `<tr><td>${k}</td><td>${v.decline_reason}</td></tr>`
, "");
$('#declinesTable').append(html);
}
const str = '{ "abc": {"decline_reason": "Business rule switched off"},"def": {"decline_reason": "No response by interface"},"ghi": {"decline_reason": "Requested incorrect size"}}'
stringParse(str);
<table id="declinesTable">
<tr>
<th>Reference Code</th>
<th>Decline Reason</th>
</tr>
</table>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

How to handle dates from database with AngularJS

I'm getting data from SQLite and assign it to my $scope.loans:
{
"id": 1,
"book_id": 2,
"patron_id": 3,
"loaned_on": "2016-12-28",
"return_by": "2017-01-25",
"returned_on": "2017-01-17",
}
{
"id": 2,
"book_id": 3,
"patron_id": 4,
"loaned_on": "2016-12-28",
"return_by": "2017-01-25",
"returned_on": null,
}
In my view I'm trying to bind the data into inputs tags so the user can edit and submit the changes (I'm using pug template engine)
table
thead
tr
th Loaned On
th Return By
th Returned On
tbody
tr(ng-repeat='loan in loans')
td(type='date' ng-model='loan.loaned_on' value='{{loan.loaned_on}}')
td(type='date' ng-model='loan.loaned_on' value='{{loan.return_by}}')
td(type='date' ng-model='loan.loaned_on' value='{{loan.returned_on}}')
Now I'm getting an AngularJS error says that the ngModel is not a date object.
I understand that I should use the date constructor to convert the date string to a date object, But my question is what is the best way to do such a thing?
solution
I thought that maybe I'll find a better way, but I didn't.
So I loop through the loans array and assign a date object for each date string.
You can just do this, which is simple and inline.
td(type='date' ng-model='new Date(loan.loaned_on)' value='{{loan.loaned_on}}')
You gave the input type as date but you assigning date string to the model which the model is not expecting. Instead, convert the value to a date object and assign it as shown below :
tbody
tr(ng-repeat='loan in loans')
td(type='date' ng-model='loan.loaned_on' value='{{new Date(loan.loaned_on)}}')
Creating a date
You can simply use the default constructor of Date, if your date is in this ISO 8601 form.
new Date("2017-01-25")
If you want to do some calculations with the date or if you want to pass the date in another format, I would recommend using moment.js:
var myDate = moment("2017-01-25", "YYYY-MM-DD");
var newDate = myDate.add(7, "days");
Passing it to the scope
The simplest way to pass the Date to the HTML is to pass it in a scope function. In this way, you can simply call it in the HTML.
Controller (with Date Constructor):
$scope.createDate = function(dateString) {
return new Date(dateString);
};
Controller (with moment.js):
$scope.createDate = function(dateString) {
return moment("2017-01-25", "YYYY-MM-DD");
};
HTML (pug template):
td(type='date' ng-model='createDate(loan.loaned_on)' value='{{loan.loaned_on}}')
Try this :
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl',function ($scope) {
$scope.loans = [{
"id": 1,
"book_id": 2,
"patron_id": 3,
"loaned_on": "2016-12-28",
"return_by": "2017-01-25",
"returned_on": "2017-01-17"
},
{
"id": 2,
"book_id": 3,
"patron_id": 4,
"loaned_on": "2016-12-28",
"return_by": "2017-01-25",
"returned_on": null
}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<table>
<thead>
<tr>
<th>Loaned On</th>
<th>Return By</th>
<th>Returned On</th>
</tr>
</thead>
<tbody>
<tr ng-repeat='loan in loans'>
<td><input type='date' ng-model='loan.loaned_on' value='{{loan.loaned_on}}'/></td>
<td><input type='date' ng-model='loan.return_by' value='{{loan.return_by}}'/></td>
<td><input type='date' ng-model='loan.returned_on' value='{{loan.returned_on}}'/></td>
</tr>
</tbody>
</table>
</div>

How to read a list of html tables in JavaScript

I have a list of HTML tables given by pandas data frame in the format of:
list_html =
[<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>score</th>
<th>id</th>
<th>name</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>0.776959</td>
<td>grade</td>
<td>grade</td>
</tr>
<tr>
<th>1</th>
<td>0.414527</td>
<td>class</td>
<td>class</td>
</tr>, ... , ... ]
I am trying to visualize this data in an html page and could not do it. I do not have enough experience in web development. My goal is to use JavaScript to loop through each item the list and visualize them below each other in html. It would be great if anybody can help!
This is what I tried so far, its probably completely wrong:
var list_html = list_html // list of html codes as a javascript variable.
var arrayLength = analysis.length;
for (var i in list_html) {
document.getElementById("analysis_1").innerHTML = list_html[i];
}
Given a valid array of strings list_html (actually list_html is not a valid array of strings, since the markup in each entry is not wrapped in quotes) and a container in the DOM with id "analysis_1" it's simply a matter of:
var container = document.getElementById('analysis_1');
for (var i = 0; i < list_html.length; i++) {
container.innerHTML += list_html[i];
}
UPDATE:
well... in your scenario there is no need at all for a loop, you can simply inject a single string by joining the elements in the array:
document.getElementById('analysis_1').innerHTML = list_html.join('');
fast and simple! :)
using jquery's selectors :
Give the 'td' which contains the data a class name, eg: 'MyTd';
Select them all: $(.MyTd).text()
Done!

How to convert a C# list of DateTimes to local JS date?

I've looped through a list of C# DateTime's on a view using Razor syntax and bound to a table on the view.
What I need to do before the values are bound to the table is convert to the browser's local time. The UpdatedTime passed in is in UTC timezone from the server.
So I need to somehow convert each UpdatedTime property in the Models.Escalation list to local before it is bound to the table.
I did try calling #item.UpdatedTime.ToLocalTime() but this converts to the server side local time which is UTC. Not the browser local time.
Question:
How can you convert a C# list of DateTime's to local on client side JS?
I do know how to convert a single DateTime value to local using a moment. But not sure how I can apply that to the complete Models.Escalation list:
var updatedTimeISO = moment.utc('#Model.UpdatedTime').toISOString();
var updatedTimeLocal = moment(updatedTimeISO);
#Model.UpdatedTime = updatedTimeLocal ;
The table loop that binds the C# DateTime's to a table in the Razor view:
<tbody>
#foreach (Models.Escalation item in Model)
{
<tr>
<td data-order="#item.UnixTimeStamp" class="td-limit">#item.UpdatedTime.ToString("f")</td>
<td class="td-limit">#item.EventName</td>
</tr>
}
</tbody>
You should be able to accomplish this on the server side if you know what timezone you want to convert too.
DateTime timeUtc = DateTime.UtcNow;
try
{
TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone);
Console.WriteLine("The date and time are {0} {1}.",
cstTime,
cstZone.IsDaylightSavingTime(cstTime) ?
cstZone.DaylightName : cstZone.StandardName);
}
catch (TimeZoneNotFoundException)
{
Console.WriteLine("The registry does not define the Central Standard Time zone.");
}
catch (InvalidTimeZoneException)
{
Console.WriteLine("Registry data on the Central Standard Time zone has been corrupted.");
}
If you don't know the browsers timezone you could use the following jQuery and moment JS code:
$(".td-limit").each(function () {
var updatedTimeISO = moment.utc($(this).data('order')).toISOString();
var updatedTimeLocal = moment(updatedTimeISO);
$(this).text(updatedTimeLocal);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.14.1/moment.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<td data-order="2013-05-02T21:01:26.0828604Z" class="td-limit"></td>
<td data-order="2013-04-02T21:01:26.0828604Z" class="td-limit"></td>
<td data-order="2013-03-02T21:01:26.0828604Z" class="td-limit"></td>
<td data-order="2013-02-02T21:01:26.0828604Z" class="td-limit"></td>
<td data-order="2013-01-02T21:01:26.0828604Z" class="td-limit"></td>
</tr>
</tbody>
</table>

Angular-Datatables wrong sorting on date

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

Categories

Resources