I have a paginated table. It's being built dynamically based on the results of a database call. I should write script code to affect all rows in table, I need to loop through all of the table rows, but it seems like I'm only able to iterate over the current rows that are visible on-screen, due to the pagination. So basically I may have 100 rows, but its only showing me rows 1-10 due to the pagination, which is expceted. But when i try to loop through the table contents, it only iterates through rows 1-10, instead of all 100 rows. Are there any API's or settings that will allow me to access all the rows?
$("#tableId").on("keyup", function () {
var value = $(this).val();
$("table tr").each(function (index) { //?
if (index !== 0) {
$row = $(this);
var id = $row.find("td:first").text();
// some script codes...
Related
My code is a simple form with 3 input fields. Once the user fills them all in and presses the button it will add a row to the table with the input data aswell as an index number. Like this:
https://imgur.com/g5ToOpF
im trying to give each row in a table an index number that is correct with the amount of rows inserted. This works but now I want it to update the index number when I remove one of the rows from the table.
The following function is triggered when the customer fills in an input field with the desired index number that they want to delete and then press a button.
function removeRow() {
let tabel = document.getElementById("tabel");
let rows = tabel.getElementsByTagName("tr");
let indexNumber = document.getElementById("indexnumber").value;
Object.entries(rows).forEach(([key]) => {
if(key === indexNumber) {
tabel.deleteRow(indexNumber);
}
})
}
This works and deletes the row that the customer whats but it doesn't update the index numbers for the other rows. So when I delete row 5. My table will look like this.
https://imgur.com/Zz3sBSI
I figure I have to loop through all of the rows and set the index to the correct number again. Can anyone help me out :) ?
For the full code check:
https://codepen.io/Botert/pen/bJLLWL
grtz,
Botert
To answer your question, try adding the following snippet in your removeRow() function:
for (var i=1; i<rows.length; i++) {
var dataRow = rows[i].children[3];
dataRow.textContent = i;
}
Fiddle here: https://jsfiddle.net/ufszamv4/
It's outside of the scope of the question, but consider taking a different approach to the problem. Try placing your rows in an object that has its properties removed. The goal is to simply delete a row without having to update the rest of the data.
Very Quick points. I have seen very similar questions here on SO but they usually use the table ID or assume there is only one table. I have a page with many tables using the same template (no unique ID) and would like to know if when a particular data is loaded, if the rows are empty. I have tried :
jQuery: count number of rows in a table
Jquery- Get the value of first td in table and many others
//var row = $(this).closest('table tbody:tr:first');
// var row = $(this).closest('tr').children('td:first').text();
// var row = $(this).closest('tr').length;
// var row = $(this).closest('tr').children('td:first').length;
// var row = $(this).closest('table').find("tbody").children().length;
// var row = $(this).closest('table').children('tr:last').index() + 1;
// var row = $(this).closest('table').rowIndex;
// var row = $("tbody").has("tr");
// var row = $(this).closest('tbody').has("tr");
var row = $('#tbody').children('tr:first').length;
But cannot get the right answer.
Below is the table structure:
To get number of rows, use length or size()
//$(this) assumed as element inside table.
$(this).closest('table').find('tr').length
As you mentioned that you've many tables in a page. you need to let jQuery identify the table index from where you want to get tr length.
To get the specific table, use eq()
//To get TR length in 2nd table of a page
$('table:eq(1) tr').length
FYI,
For class selector, use $('.table:eq(1) tr').length
Use $(document).ready(function(){} to wrap your code, that will work when your page gets ready.
Looking at your table structure,
you can use
$(".dataTable tr").length
to get the count of rows in table
$("table").each(function(){
console.log($(this).find("tr").length));
})
This will log the count of trs in all tables that you have in your page
If you want to run some code when data gets loaded into any table you got to use Mutation Observer
MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
//create observer
var observer = new MutationObserver(function(mutations, observer) {
console.log("Table Loaded");
//whatever you want to do when table is loaded
});
//set to observe childs ( options )
observer.observe(document.querySelector("table"), {
subtree: true,
childList:true,
attributes:true
});
I went through people's suggestions which mostly assumed (like the other pages) that there was an ID and that there was a single table on the page although the question mentioned it wasn't so.
Ended up using: var row = table_values.context.tBodies["0"].firstElementChild;
I got this by inspecting the tbody via dev tools.
I'm using the latest SlickGrid, with dataView.
I subscribe to the onActiveCellChanged event to react to a user selecting a row, and get the cell contents of the first column with:
grid.onActiveCellChanged.subscribe(function(e, args)
{
var cell = args.cell;
var row = args.row;
vat cell_contents = data[row][grid.getColumns()[0].field];
This works perfectly until I filter the table. Then args.row doesn't match the row in the data table.
How can I map the filtered row number (given in the event), to the actual row of the data that I want to read?
i.e. A filtered grid could yield one row of data, but could actually be row ten of the actual data table. I need to be able to read the data in the visible row selected.
After numerous attempts, I finally managed to do this. For anyone else that comes looking, what I did was:
grid.onActiveCellChanged.subscribe(function(e, args)
{
var cell = args.cell;
var row = args.row;
var row_data = dataView.getItem(row); // Read from dataView not the grid data
var cell_contents = row_data['id'];
This solution compensates for re-ordered columns as well as filtered rows.
How can I exempt a single row in a DataTables.js table from DataTables' builtin filtering, so thta it is always shown?
Background: I'm building a table editing component using the jQuery-based DataTables.js library. Instead of using dialogs or overlays, I wanted to present editing controls right within the datatable, like this:
This works like a charm, even with active filters: I keep the original, unchanged data in the record while it is being edited, so I can use that data for the 'sort' and 'filter' modes of mDataProp, and my row stays in place and visible until editing is finished.
A bigger problem arises when I add a new row: There is no data to use for filtering, so if a filter is active, my row won't be visible. This breaks the workflow where the user searches through the dataset, sees that some record is missing, and (without clearing the filter) presses the "Add" button, waiting for an empty row with edit controls to appear:
How can I exempt this special row from DataTables' filtering?
After reading through the source code of DataTables.js for some time, I came to the conclusion that there is no way to hook into the filtering in the desired way. There are hooks for custom filters, but they can only be used to hide stuff, not to show stuff.
However, there's a 'filter' event which is triggered after filtering, but before the table is rendered. My solution installs an handler for this event:
$('table#mydatatable').bind('filter', function() {
var nTable = $(this).dataTable();
var oSettings = nTable.fnSettings();
//collect the row IDs of all unsaved rows
var aiUnsavedRowIDs = $.grep(oSettings.aiDisplayMaster, function(iRowID) {
var oRowData = nTable.fnGetData(iRowID);
return is_unsaved(oRowData);
});
//prepare lookup table
var oUnsavedRecordIDs = {};
$.each(aiUnsavedRowIDs, function(idx, iRowID) {
oUnsavedRecordIDs[iRowID] = true;
});
//remove unsaved rows from display (to avoid duplicates after the
//following step)
for (var i = oSettings.aiDisplay.length; i >= 0; i--) {
//iterate backwards, because otherwise, removal from aiDisplay
//would mess up the iteration
if (oUnsavedRecordIDs[ oSettings.aiDisplay[i] ]) {
oSettings.aiDisplay.splice(i, 1);
}
}
//insert unsaved records at the top of the display
Array.prototype.unshift.apply(oSettings.aiDisplay, aiUnsavedRowIDs);
//NOTE: cannot just say oSettings.aiDisplay.unshift(aiUnsavedRowIDs)
//because this would add the array aiUnsavedRowIDs as an element to
//aiDisplay, not its contents.
});
What happens here? First, I find all unsaved rows by looking through oSettings.aiDisplayMaster. This array references all rows that are in this DataTable, in the correct sorting order. The elements of aiDisplayMaster are integer indices into DataTables' internal data storage (one index per row).
The filtering process goes through the rows in aiDisplayMaster, and places the row IDs of all matching rows in oSettings.aiDisplay. This array controls which rows will be rendered (after this event handler has finished!). The whole process looks like this:
[1, ..., numRows]
|
| sorting
v
oSettings.aiDisplayMaster
|
| filtering
v
oSettings.aiDisplay
|
| rendering
v
DOM
So after having located all unsaved records in aiDisplayMaster (using custom logic that I wrapped in an is_unsaved() function for the sake of this snippet), I add them all to aiDisplay (after removing existing instances of these rows, to avoid duplicates).
A side-effect of this particular implementation is that all unsaved rows appear at the top of the table, but in my case, this is actually desirable.
I'm using Datatables to display some data. I also have inputs that are used to add a new row to the data. When I add this row, I reinitialise the table, and it automatically sorts the new row according to the sorting rules I give it. My question is this: Is there a way to get the data from the table in the order it's currently being viewed? Whenever I try
$('#tableCompetitors').dataTable().fnGetData(),
it gives me the data in the order it was added to the table not the ordered it's being presented in.
So is there an easy way to do what I want?
P.S. If it helps. The original datasource is an array of arrays that is provided from a textbox. I parse it, push it to an array, then use that array as the datasource.
I came across this with the same question. While the accepted solution may work, I found a better way:
$("example").DataTable().rows({search:'applied'}).data()
See selector-modifier documentation for more information.
Here is one solution using 3 of the API callbacks.
Create variable for CurrentData
Reset CurrentData to empty array within fnPreDrawCallback which fires before the new table is rendered
fnRowCallback gives access to array of data for each row, push that array into CurrentData array
fnDrawCallback fires after table rendered, can now access sorted data in CurrentData array
JS
var currData = [];
$('#example').dataTable({
"fnPreDrawCallback": function(oSettings) {
/* reset currData before each draw*/
currData = [];
},
"fnRowCallback": function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
/* push this row of data to currData array*/
currData.push(aData);
},
"fnDrawCallback": function(oSettings) {
/* can now access sorted data array*/
console.log(currData)
}
});
DEMO: http://jsfiddle.net/ne24B/
Just trying to give you another option.
The following will get all the rows in the table, even if they are filtered out:
var currData = [];
var oTable = $('#example').dataTable();
oTable.$("tr").each(function(index, row){
//generate your array here
// like $(row).children().eq(0) for the first table column
currData.push($(row).children().eq(0));
// return the data in the first column
currData.push($(row).children().eq(0).text());
});
or if you just want the results that match the filter then:
var currData = [];
var oTable = $('#example').dataTable();
oTable.$("tr", {"filter":"applied"}).each(function(index, row){
//generate your array here
// like $(row).children().eq(0) for the first table column
currData.push($(row).children().eq(0));
// return the data in the first column
currData.push($(row).children().eq(0).text());
});
currData will contain the sorted list of the first column data.
Edit:
To get the entire row's text into the array.
$(row + " td").each(function(index, tdData){
currData.push($(tdData).text());
});
or
$(row).children().each(function(index, tdData){
currData.push($(tdData).text());
});
This way you have a little more control on what the array can contain. My 2 cents.