jquery: How do I access the underlying DataTable inside a createdRow() callback? - javascript

When a row is created, I would like to add a child row containing a <table>, for later population via on.click() + DataTable() + ajax. Pretty simple. The createdRow() callback seems like a great place to do this ... if I could get it to work.
createdRow() takes 4 parameters which appear to be the following.
row - HTML element of the created row
data - plain ol' JSON of the new row's data
dataIndex - the row # within its table
cells - DOM elements for the <td>s that make up the row
None of these are DataTables or child objects. Not only that, I do not seem to have a way to get at the underlying <table> element. Neither $(row).closest('table') nor $(cells[0]).closest('table') seem to return anything, and $(row).parent() doesn't work either. It seems as though the row isn't inserted into the table yet.
If the row really hasn't been inserted into the table when createdRow() is called, then I guess I just need to use another callback, like initComplete(), and iterate over rows. But createdRow() would be perfect, since all the data is right there in the args, so I hope I am just missing something simple and createdRow() can be made to work.
Thanks!

You can access a table's API object from within the table itself using one of the approaches shown here. So, for example,
$('#your_table_id_here').DataTable()
With this, you can do the following to create a child row:
$('#example').DataTable( {
"createdRow": function( row, data, dataIndex, cells ) {
var myTable = $('#example').DataTable();
myTable.row( dataIndex ).child( '<table><tr><td>some data</td></tr></table>' ).show();
}
} );
This basically uses the row() API call with the row index number to get the row as a DataTables object (instead of a <tr> element).
If you are adding a new row via the DataTables API using row.add(), then you can use the row object which is returned from that function, without needing to create a new instance of the DataTable's API:
var row = table.row.add( ['John Doe', 'more info', ...] ).draw();
row.child( '<table><tr><td>some data</td></tr></table>' ).show();
The above example assumes that table is the variable assigned to your DataTable when the DataTable is created:
var table = $('#example').DataTable( {
// your usual DataTable options here
} );
Adding a child to a row is typically done when the table is initially rendered, without using the createdRow option. I think this is the easiest way to handle things such as the open/close buttons (if you want those).
Update regarding a comment about not having access to the HTML table's ID.
Inside the createdRow callback function you can use this as a selector also: var myTable = $( this ).DataTable();. In this case, there is no need to know the ID of the table.
Using this, my earlier example becomes the following:
$('#example').DataTable( {
"createdRow": function( row, data, dataIndex, cells ) {
var myTable = $( this ).DataTable();
myTable.row( dataIndex ).child( '<table><tr><td>some data</td></tr></table>' ).show();
}
} );

Related

How to add jquery tabledit buttons to new rows of a table

How to tell to jQuery tabledit that the rows are changed? The buttons only generated for existing rows, when I add a new row (for example using jQuery), the table buttons doesn’t appear in the new row. I saw in tabledit code, that there is possibility to switch between view and edit mode (maybe this would help me), but don’t know how to access these methods after the tabledit is created and when rows has been changed.
A little snippet from my code:
$(document).ready(function(){
$(‘#btn’).click(function(){ ... adding row, I need to update tabledit here });
$(‘#table’).Tabledit(...parameters...); }
});
tabledit
Here is the best solution I could come up with for your situation.
I created an "Add" button. NOTE the for-table attribute so I can figure out what table to add to later.
<button id='add' for-table='#example1'>Add Row</button>
Then I created a click handler for the "Add" button.
$("#add").click(function(e){
var table = $(this).attr('for-table'); //get the target table selector
var $tr = $(table + ">tbody>tr:last-child").clone(true, true); //clone the last row
var nextID = parseInt($tr.find("input.tabledit-identifier").val()) + 1; //get the ID and add one.
$tr.find("input.tabledit-identifier").val(nextID); //set the row identifier
$tr.find("span.tabledit-identifier").text(nextID); //set the row identifier
$(table + ">tbody").append($tr); //add the row to the table
$tr.find(".tabledit-edit-button").click(); //pretend to click the edit button
$tr.find("input:not([type=hidden]), select").val(""); //wipe out the inputs.
});
Essentially;
Deep Clone the last row of the table. (copies the data and attached events)
Determine and set the row identifier.
Append the new row.
Automatically click the Edit button.
Clear all inputs and selects.
In my limited testing this technique appears to work.
jQuery Tabledit should be executed every time a table is reloaded. See answer given here:
refreshing Tabledit after pagination
This means that every time you reload the table (e.g. navigating to new page, refreshing etc), you must initialize Tabledit on the page of the table where it wasn't initialized. The problem is that there is no way to know whether Tabledit has been initialized on the table already, hence if you re-initialize it, duplicate buttons (edit, delete..) will be added to the rows of the table. You also cannot destroy a non-existent Tabledit, hence calling 'destroy' always beforehand will not help.
I hence created my own function to tell me if Tabledit is initialized on a certain page of a table or not:
function hasTabledit($table) {
return $('tbody tr:first td:last > div', $table).hasClass("tabledit-toolbar");
}
and using it as follows:
if( !hasTabledit($('#table')) ) {
$('#table').Tabledit({
url: 'example.php',
columns: {
identifier: [0, 'id'],
editable: [[1, 'points'], [2, 'notes']]
},
editButton: true,
deleteButton: false
});
}
The hasTabledit(..) function checks whether the last cell of the first row of the table has a div which has the tabledit-toolbar class, since this is the div that holds the Tabledit buttons. You may improve it as you like. This is not the perfect solution but it is the best I could do.

Get HTML element by JavaScript

How can I reach the first row and the first column (using javaScript) from a table in specific URL?
for example in the following URL:
https://www.w3schools.com/jsref/dom_obj_table.asp
In 'Table Object Methods', I want to get "createCaption()" .
Thanks!
you can try this...
you get value into rows of table HTML.
var row = document.getElementById("myTable").rows[0].innerHTML;
Using css you can do
var elem = element.all(by.css('table tr:nth-child(2) td:nth-child(1)').last();
This selects the first column from the second row that is in a table.
Using element.all because there are 3 tables it could apply to, which is why you need the .last() because the table you wanted referenced was the last table. Would work better if the table has an unique ID to reference it with.

Jquery DataTable Reinitialization

I am reading data from google spreadsheet from multiple sheets and displaying the retrieved data in the tabular format. I am creating table rows having data in an ajax call once data is retrieved i.e.
$tbody.append('<tr><td>'+rows[i][6]+'</td>'+'<td>'+rows[i][0]+'</td><td>'+rows[i][1]+'</td><td>'+rows[i][2]+'</td><td>'+rows[i][3]+'</td><td>'+rows[i][4]+'</td><td>'+rows[i][5]+'</td><td><a id="UpdateLink" href="#">Update</a></tr>');
On the very first run the data appears fine but when I happen to have data from another sheet I see no paging is applied and when I click any header column to perform the sort It displays data from the first sheet.
Upon google It was suggested to use destroy attribute for datatable i.e.
$("#spreadsheetdata).DataTable({
destroy:true
});
but behavior remains the same.
I have also applied
if ( $.fn.dataTable.isDataTable( '#spreadsheetdata' ) ) {
//dataTableInstance = $('#spreadsheetdata').DataTable();
}
else {
dataTableInstance = $('#spreadsheetdata').DataTable( {
paging:true,
ordering:true,
info:true
});
}
but no desirable results.
please guide thanks.
Rather adding the rows with the jQuery append method, you'll need to use the DataTables row.add() method.
If dataTableInstance is the variable you're assigning to your table and rows is the array of data from your Google spreadsheet, this syntax should allow you to append new rows to an existing table:
dataTableInstance.row.add([
rows[i][6],
rows[i][0],
rows[i][1],
rows[i][2],
rows[i][3],
rows[i][4],
rows[i][5],
'<a id="UpdateLink" href="#">Update</a>'
]).draw();
The reason appending the new rows with jQuery doesn't work is that DataTables maintains its own client-side state -- see search(), order(), and page() for examples.
So, if you add rows directly to the table body, they'll disappear as soon as you sort, search, etc.

jQuery DataTables - Access all rows data

I'm using jQuery DataTables and want to copy all rows (save in JavaScript array) upon clicking the header checkbox.
I want to find where jQuery DataTables store the HTML for remaining page of rows, so I can navigate through JavaScript then check it there or set property checked to true.
Something like this one.
Other information:
I use data from an ajax source(serverside:false), all data is returned.
When I click page 1, all the rows remain Checked.
SOLUTION
There are many methods that could be used for that purpose. You can use rows().data() to get the data for the selected rows.
Example:
var table = $('#example').DataTable();
var data = table
.rows()
.data();
alert( 'The table has ' + data.length + ' records' );
DEMO
See this jsFiddle for code and demonstration.
I find the generated element by jQuery DataTables using this code, and I can copy the whole tr element that hides when paging the DataTables.
$('#example').DataTable().rows().iterator('row', function(context, index){
var node = $(this.row(index).node());
//node.context is element of tr generated by jQuery DataTables.
});
If you do this:
$('#table').DataTable().rows().data();
you get a lot of unnecessary data.
If you just want the table data you can do this:
$('#table').DataTable().rows().data().toArray();
Using
tableObject.rows().data()
will return all the data from the table.
Set the pageLength:
$('#example').dataTable( {
"pageLength": 50
} );

X-Editable and Bootstrap datatables

I've tried with no success to implement x-editable in bootstrap datatables, the reason being when i update an element from x editable, the datatable fails to recognize those changes.. i've tried updating the table, destroying it, hidden tags, but the main problem seems to be that the datatables fails to recognize any change after the initialization..
I add the rows via button click, when they get to the table, i run .editable on those elements. they become editable but the sorting and search of the datatables doesnt work..
Can anyone help me?
The problem is that for performance reasons, Datatables caches the table into memory so actually the DOM table is different from the in-memory table. And when you modify the DOM, it doesn't change the table in-memory.
Therefore, Datatables created a function helper : invalidate() that you can apply on a row http://datatables.net/reference/api/row%28%29.invalidate%28%29 (there is a multiple rows version too).
Or you can still use the function data() which is less CPU consuming (recommended).
I would do something like this :
$('.xeditable').on('save', function(e, params) {
var $tr = $(e.target).closest('tr');
var newValue = params.newValue;
//If you didn't save the datatable into a var table, you need to call this line :
//var table = $('#example').DataTable();
table.row(tr).data(newValue);
//Or table.row(tr).invalidate(); which should read from the DOM directly
});

Categories

Resources