How to generate jQuery DataTables rowId client side? - datatables

The jQuery DataTables reference shows an example of setting the rowId option to a column from the data source (server side). This setting is used for the "select" extension and retaining row selection on Ajax reload.
Is there any way to generate the row identifier value 1) client side, or 2) as a combination of multiple columns from the data source?
Example data source:
{
"data": [
{
"aid": 5421,
"bid": 4502,
"name": "John Smith"
}
}
Code:
$("#datatable").DataTable({
select: true,
//rowId: "aid" each row ID is the value of the "aid" column
// e.g., <tr id="5421">
//rowId: 0 each row ID is the value of the 0-indexed column
// e.g., <tr id="5421"> (same as above)
rowId: [0, 1] // How? row ID combined value of 2+ columns
// e.g. <tr id="5421-4502">
rowId: "random" // How? random generated client-side ID
// e.g., <tr id="id34e04">
});

Apparently there's no way to do this directly. As a workaround, you could use the ajax.dataSrc option and/or the rowId option:
// Example using dataSrc option to manipulate data:
$("#example").dataTable({
ajax: {
url: "data.json",
dataSrc: function (json) {
for (var i = 0, ien = json.data.length; i < ien; i++) {
json.data[i][0] = 'View Message';
}
}
}
});

This worked for me:
$("#datatable").DataTable({
...
'createdRow': function(nRow, aData, iDataIndex) {
$(nRow).attr('id', 'row' + iDataIndex); // or if you prefer 'row' + aData.aid + aData.bid
},
...
});
I updated it from a question that seems to be a duplicate of this one. The createdRow callback is documented here.

Related

Comparing two different data objects in Vue while reducing

I have existing data objects and a function which is looping through by employee and doing some light math (all of this is currently working as it needs to)
The thing that I need to add into this is allow my loop to do another check as it moves through. As I'm moving through my data_record object, I need to check the ID in my Data_record object against the ID in the boxes. If they match, I need to check stock_numbers against box_numbers. If stock_numbers is greater than box_numbers then I want to put "Not Available" as a string into my computed object so that I can show that in my template instead of the data.
I have a sandbox linked below where one file is doing this code shown below, but the file main.js is trying to match up the entries so that I can then compare data on the matches, however, it is currently only returning the entries of the first one that don't have a match
How can I properly match entries between objects and compare data of those matches while still performing this current reduce function?
<tr v-for="(labels, employee) in numbersByEmployee" :key="employee">
<td>#{{ employee }}</td>
<td v-for="date in dates" :key="date">#{{ labels[date] && labels[date].qty * labels[date].labels }}</td>
<td>#{{ labels.total }}</td>
</tr>
new Vue({
el: "#app",
data: {
data_record: [
{
employee: "Adam",
ID: "Ac1874/12-15",
Shelf_Date: "2021-07-14",
stock_numbers: 100,
labels: 25
}
],
boxes: [
{
ID: "Ac1874/12-15",
box_numbers: 50,
reception_date: "2021-07-20"
}
],
dates: ["2021-07-14", "2021-07-15"]
},
computed: {
numbersByEmployee() {
return this.data_record.reduce((r, o) => {
r[o.employee] ??= {};
r[o.employee][o.Shelf_Date] ??= {
stock_numbers: 0,
labels: 0,
total: 0
};
r[o.employee][o.Shelf_Date].stock_numbers += +o.stock_numbers;
r[o.employee][o.Shelf_Date].labels += +o.labels;
r[o.employee].total ??= 0;
r[o.employee].total += +o.stock_numbers * +o.labels;
return r;
}, {});
}
}
});
Code sandbox with this portion of code, as well as a work in progress for the matching (the main.js file is where I'm just trying to match up the two objects but it's currently showing the entries that don't match)
https://codesandbox.io/s/charming-glitter-83nzg?file=/src/main.js
EDIT (output for reduce function)
Currently, numbersByEmployees dumps
"Adam": { "2021-07-14": { "labels": 5, "stock_numbers": 40, "total": 0 }, "total": 200 }
You can use array.prototype.find to look in the box array for the id of the current item in record_data
I've forked your examaple to demonstrate this. I renamed some of the variables to match your code on stackoverflow.
https://codesandbox.io/s/agitated-diffie-ntmru
Let me know if I can edit this to better fit your need.

Sorting date in datatable

I'm trying to sort dates in my datatable like DD/MM/YYYY (day, month, year) .
I was following https://datatables.net/plug-ins/sorting/ .
but all the date sorts seem to be deprecated and point to the datetime plugin: https://datatables.net/blog/2014-12-18
I don't seem to be able to get the datetime plugin working to sort. I tried the old way, with date. The initialize looks like this:
var historiektable = $('#dataTableHistoriek').DataTable({
"paging" : false,
"ordering" : true,
"scrollCollapse" : true,
"searching" : false,
"columnDefs" : [{"targets":3, "type":"date"}],
"bInfo": true
});
Without sorting it shows the table results like this:
When I put ordering:true 2 of the 2016 dates appear somewhere else in the list (so, not in order you would expect)
With everything pointing at Moment I thought I needed to sort with that. But I'm not sure how.
I saw $.fn.dataTable.moment('DD.MM.YYYY'); somewhere, but I understood that the fn doesn't work with this newest version of datatables anymore?
Anyone knows how to sort dates?
Use date-eu sorting plugin to sort dates in the format DD/MM/YY.
Include the following JS file //cdn.datatables.net/plug-ins/1.10.11/sorting/date-eu.js and use the code below:
var historiektable = $('#dataTableHistoriek').DataTable({
"paging" : false,
"ordering" : true,
"scrollCollapse" : true,
"searching" : false,
"columnDefs" : [{"targets":3, "type":"date-eu"}],
"bInfo": true
});
The example of Gyrocode.com seems the most effective. A recent solution says to use Moments.js but it does not work in my case. date-eu is deprecated by DataTables but it works perfectly.
If you want to sort by date and time using the date format dd/MM/yyyy HH:mm, use date-euro in the same way.
var table = $('#example-table').DataTable({
columnDefs: [{ 'targets': 0, type: 'date-euro' }],
order: [0, 'desc'],
});
For beginners, add the JS file date-euro to your site. Then add "columnDefs" in your code to indicate which column date-euro should be applied: targets = indicates the column containing the dates to sort, type = indicates the date-euro function to apply to the column. Finally, add "order" to apply the sort you want.
Please look into this answer for an alternate way to sort data by date.
Sample code::
<td data-search="21st November 2016 21/11/2016" data-order="1479686400">
21st November 2016
</td>
$('#dataTable').DataTable({
"order": [[10, 'desc']],
});
Thank You,
Happy Coding :)
Please refer to this pen: https://codepen.io/arnulfolg/pen/MebVgx
It uses //cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.4/moment.min.js and //cdn.datatables.net/plug-ins/1.10.12/sorting/datetime-moment.js for sorting datatable
To sort the table by default use:
$.fn.dataTable.moment('DD/MM/YY');
$('#example').DataTable({
"order": [[ 3, "desc" ]]
});
Following Plasebo's example works, but in my case the MySQL DATE_FORMAT was sorting on month value, not entire date. My solution was to remove the DATE_FORMAT from my SQL statement.
$(document).ready(function() {
$.fn.dataTable.moment('DD/MM/YY');
$('.happyTable').DataTable({
"ordering": true,
"order": [[ 1, "desc" ]],
});
});
DATE_FORMAT(date,'%m/%d/%Y')
"2003-12-30 00:00:00"
results in "12/30/2003" but sorts on month value.
You can do your own comparator in order to keep the control of how is ordering the dates.
jQuery.extend(jQuery.fn.dataTableExt.oSort, {
"ddMmYyyy-pre": function (a) {
a = a.split('/');
if (a.length < 2) return 0;
return Date.parse(a[0] + '/' + a[1] + '/' + a[2]);
},
"ddMmYyyy-asc": function (a, b) {
return ((a < b) ? -1 : ((a > b) ? 1 : 0));
},
"ddMmYyyy-desc": function (a, b) {
return ((a < b) ? 1 : ((a > b) ? -1 : 0));
}
});
As you can see in the above comparator you can choose how to parse the date depending on your data.
And in the columns definition:
"columnDefs": [
{
targets: [4], type: "ddMmYyyy"
}]
For me, using ASP.NET core 3.1 with MVC, I used a data-sort attribute on my <td> for the datatables:
<td data-sort="#(item.DueDateTime.Ticks)">
#Html.DisplayFor(modelItem => item.DueDateTime)
</td>
No plug-ins needed
See this link:
https://datatables.net/examples/advanced_init/html5-data-attributes.html
There's an ugly hack that I've used in the past especially when I couldn't quickly modify the DataTable javascript. You can add a hidden span that has the date in a sortable format.
<td><span style="visibility:hidden">2006-12-21</span>21/12/2006</td>
test
strong text
$.fn.dataTableExt.oSort['time-date-sort-pre'] = function(value) {
return Date.parse(value);
};
$.fn.dataTableExt.oSort['time-date-sort-asc'] = function(a,b) {
return a-b;
};
$.fn.dataTableExt.oSort['time-date-sort-desc'] = function(a,b) {
return b-a;
};
var table = $('#example').DataTable({
columnDefs : [
{ type: 'time-date-sort',
targets: [0],
}
],
order: [[ 0, "desc" ]]
});

Filter other columns based on first columns

I'm using jquery data tables and I'm assigning an array of values to the initialization of the data table. The table basically looks like this.
based on an an radio button I would like to limit the items that are display in the table and the items that are searched in the table.
For my example it would be based on the "Chart column". I want to limit the table to only show the items that are based on chart "D" or Chart "S". Here is how I'm initializing the table.
if (!$.fn.DataTable.isDataTable( '#fundLookUptbl' ) ) {
fundTable = $('#fundLookUptbl').DataTable( {
data: funds,
columns: [
{ "mData": "chart" },
{ "mData": "fund" },
{ "mData": "orgDefault" },
{ "mData": "progDefault" }
]
} );
var filteredData = fundTable
.columns( [0, 1] )
.data()
.eq( 0 )
.filter( function ( value, index ) {
return value = 'D' ? true : false;
} );
}
This is obviously not working, and the filterData variable is a lousy attempt on trying to make it work. I'm having a hard time understanding the API's. So the question is , How can initialize the table to only show the items that are based on a given chart. I know that I can remove the items of the array but i don't want to do that since I would simple like to be able to switch between chart "D" and "S" but still continue to search through the other columns.
I believe that filtering the column would solve your problem.
table.column(0).search('Bruno').draw()
So you could just filter the column when the radio button selection change
Here is a fiddle example
I´m not sure to be understanding what you want to do but here are some options:
One way is selecting by default value example "s". You can use a dropdown is easier to handled .Then select with jQuery the dafault value "s" on that dropdown and add a function
$("#DropdownId").change(function () {
var chart=$("#DropdownId").val();
});
$.ajax({
url: "url")",//url to reload page with new value
type: "POST",
data: {chart:chart},
success: function (data) {
}
});
});
on this way the filter is on backend. If you want to do something on the row depending of a column value you shoud to add something like this
"fnRowCallback": function (nRow, mData, iDisplayIndex, iDisplayIndexFull) {
if (mData["chart"] =="s") {
return nRow;
}
},
Datatables: custom function inside of fnRowCallback.
Good luck
fundTable.order( [0, 'asc'] );
Try that or look at this particular page for reference:
https://datatables.net/reference/api/order%28%29
Basically orders in pair of columnIndex in either asc(ending) or desc(ending) order.

jQuery Datatables highlighting row

I'm using datatables version 1.9.4 and am having a problem with adding a class to certain rows.
I have multiple datatables, all with class 'display'. I'm using jQuery tabs to display each datatable on a separate tab.
All is working well, except I want to add a class to a table row depending on the column values; if column 6 is less than column 14, I want to add myClass.
I've found suggestions to use fnRowCallback, but I'm getting random results, such as sometimes if column 6 is less than column 14, myClass gets added correctly, but other times if column 14 is less than column 6 myClass still gets added!
This doesn't happen for all rows though, so it's pretty random.
Here's the code I'm using
$(document).ready(function() {
$('.display').dataTable({
"bJQueryUI": true,
"sPaginationType": "full_numbers",
"bProcessing": true,
"bServerSide": true,
"bScrollCollapse": true,
"sScrollY": "300px",
"sAjaxSource": "ajax.php",
"sDom": '<"H"lfr>t<"F"ipS>',
"oScroller": {
"loadingIndicator": true
},
"fnRowCallback": function( nRow, aData ) {
var $nRow = $(nRow);
if (aData[6] < aData[14]) {
$nRow.addClass("myClass");
}
return nRow
}
});
});
Is there something wrong with what I've done, or is it because I'm using multiple tables?
I think I have this working, but there is probably a cleaner way, so if anyone knows of a better way of doing this, please let me know!
I'm looping through all the rows for each table once the table has been drawn.....
"fnDrawCallback": function( oSettings ) {
for (var i = 0, row; row = oSettings.nTable.rows[i]; i++) {
price = Number(row.cells[4].innerHTML.replace(/[^0-9\.]+/g,""));
average = Number(row.cells[6].innerHTML.replace(/[^0-9\.]+/g,""));
if (price < average) {
row.className = row.className + " myClass";
}
}
}

View pictures or images inside Jquery DataTable

May I know if it is possible to put pictures or images into the rows of DataTables (http://datatables.net/) and how does one goes in doing it?
yes, simple way (Jquery Datatable)
<script>
$(document).ready(function () {
$('#example').dataTable({
"processing": true, // control the processing indicator.
"serverSide": true, // recommended to use serverSide when data is more than 10000 rows for performance reasons
"info": true, // control table information display field
"stateSave": true, //restore table state on page reload,
"lengthMenu": [[10, 20, 50, -1], [10, 20, 50, "All"]], // use the first inner array as the page length values and the second inner array as the displayed options
"ajax":{
"url": "#string.Format("{0}://{1}{2}", Request.Url.Scheme, Request.Url.Authority, Url.Content("~"))/Home/AjaxGetJsonData",
"type": "GET"
},
"columns": [
{ "data": "Name", "orderable" : true },
{ "data": "Age", "orderable": false },
{ "data": "DoB", "orderable": true },
{
"render": function (data, type, JsonResultRow, meta) {
return '<img src="Content/Images/'+JsonResultRow.ImageSrcDB+'">';
}
}
],
"order": [[0, "asc"]]
});
});
</script>
[edit: note that the following code and explanation uses a previous DataTables API (1.9 and below?); it translates easily into the current API (in most cases, just ditch the Hungarian notation ("fnRowCallback" just becomes "rowCallback" for example) but I have not done so yet. The backwards compatibility is still in place I believe, but you should look for the newer conventions where possible]
Original reply follows:
What Daniel says is true, but doesn't necessarily say how it's done. And there are many ways. Here are the main ones:
1) The data source (server or otherwise) provides a complete image tag as part of the data set. Don't forget to escape any characters that need escaping for valid JSON
2) The data source provides one or more fields with the information required. For example, a field called "image link" just has the Images/PictureName.png part. Then in fnRowCallback you use this data to create an image tag.
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
var imgLink = aData['imageLink']; // if your JSON is 3D
// var imgLink = aData[4]; // where 4 is the zero-origin column for 2D
var imgTag = '<img src="' + imgLink + '"/>';
$('td:eq(4)', nRow).html(imgTag); // where 4 is the zero-origin visible column in the HTML
return nRow;
}
3) Similar to above, but instead of adding a whole tag, you just update a class that has the image as a background. You would do this for images that are repeated elements rather than one-off or unique pieces of data.
You mean an image inside a column of the table?
Yes, just place an html image tag
like this
<img src="Images/PictureName.png">
instead of putting data (some string) into a column just put the above html tag....
Asp.net core DataTables
The following code retrieve the image from a folder in WWWroot and the path in the DB field ImagePath
{
"data": "ImagePath",
"render": function (data) {
return '<img src="' + data + '" class="avatar" width="50" height="50"/>';
}
}
In case the Name of the picturefile is put together out of one or more informations in the table, like in my case:
src="/images/' + Nummer + Belegnummer + '.jpg"
you can make it that way:
var table = $('#Table').DataTable({
columnDefs: [
{
targets: 0,
render: getImg
}
]
});
function getImg(data, row, full) {
var Nummer = full[1];
var Belegnummer = full[4];
return '<img src="/images/' + Nummer + Belegnummer + '.jpg"/>';}
The picture is in the first column, so Targets = 0 and gets the Information from the same row.
It is necessary to add the parameters data and row.
It is not necessary to outsource it into a seperate function, here getImg, but it makes it easier to debug.