I'm using DataTables (datatables.net) to display data from an Ajax source and having trouble customizing it. One thing I would like to do is add a column so I can have for example an 'edit' button for each row.
The closest thing to that in the examples is here but I can't get that to work with an ajax source.
Currently, I'm using the following code to display my table:
fnServerObjectToArray = function ( aElements ){
return function ( sSource, aoData, fnCallback ) {
$.ajax( {
"dataType": 'json',
"type": "POST",
"url": sSource,
"data": aoData,
"success": function (json) {
var a = [];
for ( var i=0, iLen=json.aaData.length ; i<iLen ; i++ ) {
var inner = [];
for ( var j=0, jLen=aElements.length ; j<jLen ; j++ ) {
inner.push( json.aaData[i][aElements[j]] );
}
a.push( inner );
}
json.aaData = a;
fnCallback(json);
}
} );
}
}
$(document).ready(function() {
$('#example').dataTable( {
"bProcessing": true,
"sAjaxSource": 'get_data.php',
"fnServerData": fnServerObjectToArray( [ 'username', 'email' ] )
} );
});
Why don't you use fnRenderFunction in the aoColumns? As an example:
aoColumns: [ { "bVisible": false} , null, null, null, null,
{ "sName": "ID",
"bSearchable": false,
"bSortable": false,
"fnRender": function (oObj) {
return "<a href='EditData.php?id=" + oObj.aData[0] + "'>Edit</a>";
}
}
]
You can use it to format the value from the server side.
See similar example on the http://jquery-datatables-editable.googlecode.com/svn/trunk/ajax-inlinebuttons.html (ignore specific settings for the editable plugin)
I've created columns with edit button and links and so on, but usually i do everything server side by custominzg the data i return and then show/hide them with the aoColumns option. I don't really understand what you are tring to achieve: display server side data as a link?
Had the same problem a few months back. This is what I did.
By no means an elegant slution, but this worked.
As you might already know, DataTables do have an overload to accept Javascript Arrays.
So I made by $.ajax call. got my json, parsed it to a javascript array and then while parsing I created an extra element (an anchor tag) with href="edit.php?email=passed_email" Then on the column headers and added a column called Edit. Those values were fed to "aaData" and "aoColumns". And then the table was populated.
And BTW, if you looking for inline editing, check the following link.
DataTables editing example - with jEditableplugin
i have some RND on this problem and get this hope this will help you out.
Related
so I'm trying to change the td class of my datatables elements dynamically. From my research i found fnRowCallback, it seems to be the solution but I can't get it to work. From 1 of the questions here at Stack I found:
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
for (var i in aData) {
// Check if a cell contains data in the following format:
// '[state] content'
if (aData[i].substring(0,1)=='[') {
// remove the state part from the content and use the given state as CSS class
var stateName= aData[i].substring(1,aData[i].indexOf(']'));
var content= aData[i].substring(aData[i].indexOf(']')+1);
$('td:eq('+i+')', nRow).html(content).addClass(stateName);
}
}
}
But this does not work for me, I get the error: Uncaught SyntaxError: Unexpected token, and my elements keep the "[class name] content" format. Here is my javascript function:
$('#tableId').DataTable({
"ajax" : "function.php",
"columns" : [
{
"data" : "id"
}, {
"data" : "firstElement"
}, {
"data" : "secondElement"
}, {
"data" : "thirdElement"
}],
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
for (var i in aData) {
// Check if a cell contains data in the following format:
// '[state] content'
if (aData[i].substring(0,1)=='[') {
// remove the state part from the content and use the given state as CSS class
var stateName= aData[i].substring(1,aData[i].indexOf(']'));
var content= aData[i].substring(aData[i].indexOf(']')+1);
$('td:eq('+i+')', nRow).html(content).addClass(stateName);
}
}
},
"iDisplayLength": 5,
"scrollX": true,
"orderFixed": [[ 0, "asc"]]
});
function.php gives me a JSON with all the fields, and in the ones I want the class altered I use "[class name] content" in the field. Any ideas on how to get it to work?
Thanks
Problem with your code is that aData would be an associative array, for example:
{ "id": 1, "firstElement": "[class] content" }
When you enumerate properties with for...in construct, i would hold property name (id, firstElement) and not numerical index.
Therefore you cannot use i to access cell within given row.
Another problem with your code is that it sets HTML content after it has been created. jQuery DataTables will be unaware that you've updated cell content.
How to populate a HTML5 table if you receive data in JSON format in jQuery Ajax and based on a specific column on a row color that row on a table (Using bootstrap 4 CSS styles?)
For example if i receive a dataset in JSON format like this:
{ "name":"John", "age":31, "city":"New York" };
The column city is New York so the table row should be colored green so the finished product should be like this:
<tr class="success">
<td>John</td>
<td>31</td>
<td>New York</td>
</tr>
I'm fairly new at jQuery can anyone guide me through how this can be achieved?
I'm using datatables library at the moment and what i have done is this:
function btnSearch_Click() {
$.ajax({
type: "POST",
url: "index.aspx/GetJobs",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data) {
$('.table-sortable').dataTable({
destroy: true,
data: data,
columns: [
{
'd': 'Name'
},
{
'd': 'Age'
},
{
'd': 'City'
}]
});
}
});
};
Current HTML5 code is displayed bellow
<table class="table table-hover thead-inverse table-bordered table-sortable">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>City</th>
</tr>
</thead>
</table>
But when I click the button no data rows are returned by the browser (SQL Server does return data). Also as i mentioned i do not know how to accomplish that if specific data is returned in a row i need to color it...
Thank you for your help in advance...
Try this :
$('.table-sortable').dataTable({
destroy: true,
data: data,
columns: [
{ "data": "name" },
{ "data": "age" },
{ "data": "city" },
]
});
For using DataTables with ajax you usually have something like this:
$(document).ready(function () {
$('.table-sortable').dataTable({
"ajax": {
"url": "index.aspx/GetJobs",
"type": "POST"
},
"columns": [
{ "data": "name" },
{ "data": "age" },
{ "data": "city" },
]
});
});
As you can see the plugin itself has the functionality to use ajax.
So by default your returned data from server should contain a property data which contains the elements that are about to be rendered. You can actually specifiy this by using the dataSrc (reference) prop of ajax, you can set it to other name or remove it if you use plain collection:
"ajax": {
"url": "index.aspx/GetJobs",
"type": "POST"
"dataSrc": ""
},
This however does not change the data name in columns declaration so don't change it there.
You can read more about accepted formats and see examples in the official documentation.
Now regarding your question about row styling, there are a lot of callbacks and declarations which you can use to achieve that. I personally prefer using the createdRow callback (reference):
"createdRow": function( row, data, dataIndex ) {
if ( parseInt(data[1]) >= 18 ) {
$(row).addClass( 'success' );
}
}
So in this case if the age (second column based on 0-start-indexing) of the current row is above 18 it will add the desired class.
I hope this helps resolving your issues, if there still are problems you can try making a working jsfiddle so we can try debugging it in a "real-like" situation.
This is just to get an idea, i will add button click code
$("button").click(function(){
var obj = JSON.parse('[{ "name":"John", "age":30, "city":"New York"},{ "name":"John1", "age":30, "city":"New York"}]');
var t = $('#example');
for (i = 0; i < obj.length; i++) // iterate data from json
{
var name = obj[i].name;
var age = obj[i].age;
var classStyle = 'yellow'
if(name=='John')
{
classStyle = 'green';
}
$('#example').append('<tr style=background:'+classStyle+'><td>'+name+'</td><td>'+age+'</td></tr>');
}
});
I was able to successfully implement Datatables using the jQuery library. The problem is that when i click on page 2 in the pagination area it acts fine however when I go back to page 1 the records i selected are no longer selected.
Here is what it's supposed to do: datatables select row example
I updated my datatables to version: 1.10.15
Here is my call to handle the click event:
$("#datatable_users tbody").on("click","tr",function(){$(this).toggleClass("selected");});
Here is my code for creating the DataTable:
$("#datatable_'.$ref.'").dataTable({
"iDisplayLength": '.$itemlimit.',
"language": {
"url": "http://cdn.datatables.net/plug-ins/1.10.12/i18n/English.json"
},
"processing": true,
"serverSide": true,
"ajax": { // define ajax settings
"url": \''.Pluto::registry('web_base_uri').'service/datatable?req=1&ref='.$ref.'\',
"data": function(data) {
var datafilter= $("form#JqueryDataTableFormFilter_'.$ref.'").serializeControls();
$.each(datafilter, function(key, value) {
data[key] = value;
});
//console.log(datafilter);
}
},
"orderCellsTop": true,
"dom": "Bfrtip",
buttons: [
{
"text": "'.$search_label.'",
"className":"btn btn-default BtnjQueryDataTableFilter",
"action": function ( e, dt, node, config ) {
dt.ajax.reload();
}
}
]
});
As in server side processing the DataTable gets redrawn when you paginate so you need to keep track of what all was selected before clicking the next page and manually highlight the selected rows after each page click.
Here's an exact same working example featured on their website.
https://datatables.net/examples/server_side/select_rows.html
Let me know if you have any questions.
using DataTables, I can see this error in the console, even if my table is correctly displayed ... I guess it's not so important but could it have any collateral effect late ?
the error in the console is :
## assets => DataTable-1.10.9/js/jQuery.dataTables.js
Uncaught TypeError: Cannot read property 'replace' of null
and the faulty line is : var sTitle = col.sTitle.replace( /<.*?>/g, "" )
#### DataTable-1.10.9/js/jQuery.dataTables.js
function _fnSortAria ( settings )
{
var label;
var nextSort;
var columns = settings.aoColumns;
.../...
// ARIA attributes - need to loop all columns, to update all (removing old
// attributes as needed)
for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
{
var col = columns[i];
var asSorting = col.asSorting;
var sTitle = col.sTitle.replace( /<.*?>/g, "" );
var th = col.nTh;
../...
Checking it, col.sTitle is null... no default settings
The DataTables.net documentation ( https://datatables.net/reference/option/columns.title ) indicates 2 ways of setting the column titles : I am using the columns() way, and all my titles are correctly displayed ... It doesn't indicates WHEN we should use one way or the other way ...
$('#example').dataTable( {
"columnDefs": [
{ "title": "My column title", "targets": 0 }
]
} );
$('#example').dataTable( {
"columns": [
{ "title": "My column title" },
null,
null,
null,
null
]
} );
I "guess" it's related to the fact I am using the DataTable API rather than the jQuery dataTable selector ...
# here is my table initialisation
// Let datatables render it now - accessing API
var table = $('#sheet').DataTable({
dom: "<'row'<'col-xs-6'><'col-xs-6'f>r>t<'row'<'col-xs-6'l><'col-xs-6'p>>",
language: { url: langUrl },
ordering: true,
searching: true,
paging: true,
info: false,
select: true,
data: sheet.data,
columns: column_titles
columnDefs: [{"targets": [ 0 ],"visible": false}]
});
I have a function that creates an instance of DataTables and for some reason it initializes n-times after destruction. I only noticed this because I add custom fields on init and they were multiplying. I could prevent that but that only deals with the symptom.
To clarify, after I "destroy: the instance and reinitialize it, to change the data source, if it's the second time it initializes twice. Three times if it's the 3rd time, etc.
I speculate that the table variable is part of the closure formed by the function because even if I set table = null the same thing happens.
How can I prevent this?
DataTables Function
/*Create a DataTable on tableElementID using pageUrl as the source*/
function ajaxLoadTable ( pageUrl, tableElementID ) {
window.table = $(tableElementID)
.on( 'init.dt', function () {
//The success function is used internally so it should NOT be overwritten, have to listen for this event instead
//Add our custom fields _length refers to an element generated datatables
if ( additionalElements.saveButton ) {
$(tableElementID + '_length').after('<div class="dataTables_filter"><button>Save All Edits</button></div>');
}
if ( additionalElements.selectState ) {
$(tableElementID + '_length').after('<div class="dataTables_filter"><label>Project State: <select name="projectState" style="width:auto;"><option>Select ...</option><option value="Active">Active</option><option value="Historical">Historical</option></select></label></div>');
}
if ( additionalElements.searchBox ) {
$(tableElementID + '_length').after('<div class="dataTables_filter"><label>Search:<input type="search" id="customSearch" style="width:auto;"></label></div>');
}
})
.DataTable({
"processing": true,
"serverSide": true,
"ajax":{
type: "POST",
url: pageUrl,
data: function ( additionalData ) {
$('.serverData').each( function( index, element ){
if( element.nodeName === "SELECT"){
additionalData[element.name.toUpperCase()] = element.options[element.selectedIndex].value;
return true; //return true is equivalent to continue for $.each
}
additionalData[element.name.toUpperCase()] = element.value;
});
},
dataType: "json"
},
"pageLength": 4,
"lengthMenu": [ 4, 8, 12, 16, 24 ],
"searchDelay": 1500,
"columnDefs":
{ "targets": 0,
"orderable": false,
"data": {
"_": "display"
}
}
});
}
Destruction Function
/*Load the selected project state*/
$('html').on( 'change' , '[name=projectState]' ,function(){
var currentState = $('option:selected', this).val();
$('#projectState').val(currentState);
//Remove the old table records and the datatables. Order matters, otherwise there is unsual behavior.
if( $.fn.DataTable.isDataTable( '#searchTable' ) ) {
window.table.destroy();
window.table = null;
}
$('.projectStateText').html( currentState );
//Get the new table records
ajaxLoadTable( *some undisclosed URL*, '#searchTable');
});