Add rows to a JQuery DataTable without redrawing - javascript

How can you add rows to a JQuery DataTable without redrawing the entire table?
The behavior I would like is for it to find the correct location (based on the sort) to insert the row into the table while maintaining scroll position of the table and pagination if any.

I was facing the same problem. The solution i found for this were a new function with the name
fnStandingRedraw http://datatables.net/plug-ins/api/fnStandingRedraw.
I added the above code to be able to use this function,
$.fn.dataTableExt.oApi.fnStandingRedraw = function (oSettings) {
if (oSettings.oFeatures.bServerSide === false) {
var before = oSettings._iDisplayStart;
oSettings.oApi._fnReDraw(oSettings);
// iDisplayStart has been reset to zero - so lets change it back
oSettings._iDisplayStart = before;
oSettings.oApi._fnCalculateEnd(oSettings);
}
// draw the 'current' page
oSettings.oApi._fnDraw(oSettings);
};
After that i execute the following commands,
theTable.fnAddData([reply], false);
theTable.fnStandingRedraw();
where,
theTable: is the datatable variable (var theTable = $('#example').dataTable();).
reply: is the information i add to a row of mine datatable. More on http://datatables.net/plug-ins/api/fnStandingRedraw.
The first command adds a row on the table without redrawing it. After this, the new row will not being displayed on the table.
The second command redraws the table, so the new raw will appear, but retain the current pagination settings.
This worked fine for me.

Use dataTable().fnAddData()
http://datatables.net/ref#fnAddData
Example:
http://www.datatables.net/release-datatables/examples/api/add_row.html

Related

Assigning Row_Ids to dynamically added rows in Datatables

I am working on making an editable Datatable using Jeditable. I need to be able to dynamically add rows, which I have successfully done. By default, it appears that Datatables will add everything with a row_id of 0, which makes it impossible to differentiate added rows from each other.
So I am working on a function that assigns the row_id. There are no errors, but it also does not seem to work as it still returns a row_id of 0 for all added rows.
$('#addRow').on( 'click', function () {
var rowIndex = $('#example').dataTable().fnAddData([ "column1Data", "column2Data"]);
var row = $('#example').dataTable().fnGetNodes(rowIndex);
$(row).attr('id', row_id_counter);
row_id_counter ++;
Entire code:
http://jsfiddle.net/j2frzerj/
I tested your code in the fiddle provided, and it is adding new table rows with sequential id's, starting with index 0. I am not seeing any duplicate id's of 0?
http://prntscr.com/ew3tg9
http://prntscr.com/ew3tlr

jQuery DataTable : Delete row and reload

Now, I am working with jQuery DataTable. Everything is going well in intializing data tables with javascript data array.
In my table, it included remove row button. When I clicked the Remove button of each row, I delete record using following function.
function removeRow(itemList, recordIndex){
itemList.splice(recordIndex, 1);
dataTable.clear();
dataTable.rows.add(itemList);
dataTable.columns.adjust().draw(false);
}
This function performed well with no error. At that, I set false to draw() function to prevent going to first page when delete records in any other page.This one also working for me.
The problem is, when my itemList has 11 records, and I go to second page of data table and delete the 11th record.
So, my itemList will left only 10 record and My data table should show the first page of paging.
But, jQuery data table is not doing that. It still have in second page with no records.
I don't know how to fix that one. I want to show previous page after delete every records from current page.
I know `draw()`` function without false parameter will go to first page. But it go to first page in every deletion.
I only want to go to previous page, when I deleted all records from current page.
Please, help me. Thanks.
I found an hacky way to get the previous pagination when the current has been emptied.
It is specific to jQuery DataTable, since using it's class naming.
Try it in CodePen.
function removeRow(recordIndex){
// Get previous pagination number
var previousPagination= parseInt( $(document).find(".paginate_button.current").data("dt-idx") ) -1;
// Splice the data.
data.splice(recordIndex,1);
myTable.clear();
myTable.rows.add(data);
myTable.columns.adjust().draw(false); // May ajust the pagination as empty... `.draw(false)` is needed.
// Decide to redraw or not based on the presence of `.deleteBtn` elements.
var doIdraw=false;
if($(document).find(".deleteBtn").length==0){
doIdraw=true;
}
myTable.columns.adjust().draw(doIdraw); // Re-draw the whole dataTable to pagination 1
// If the page redraws and a previous pagination existed (except the first)
if(previousPagination>1 && doIdraw){
var previousPage = $(document).find("[data-dt-idx='" + previousPagination + "']").click();
}
// Just to debug... Console.log the fact that only one pagination is left. You can remove that.
if(previousPagination==0 && doIdraw){
}
}
Notice that I used:
#myTable as the table id
.deleteBtn as the delete buttons class
data as the dataTable data
I removed all console.log() and example related code in the code above (but not in CodePen).
"Delete this →" button handler is:
$("#myTable").on("click",".deleteBtn",function(){
var rowElement = $(this).closest("tr");
var rowIndex = myTable.row(rowElement).index();
removeRow(rowIndex);
});

Refresh Datatable 1.9 without deleting all the rows

I'm using dataTables js 1.9
An ajax call to the server get's information from the server that I want to be displayed in the table every 60 seconds or so.
I have no problems implementing solution that clears table and repopulates it:
$(id).dataTable().fnClearTable();
for( var i = 0 ; i < json.response.length; i++ ){
$(id).dataTable().fnAddData([ json.response[i] ]);
}
Issue is that the user will get pushed back to page 1 each tome the reload happens since table will be empty momentarily and it will only have 1 page then.
I would like to implement a solution where I first search for rows not in the result, remove those, then add rows that are not in the table. For this I would need to be able to target a row by a value, and I cannot find it in http://datatables.net/docs/DataTables/1.9.4/DataTable.html
Anyone has any ideas on how to do this?
You don't need to delete the data and re-populate it, you just need to redraw it.
var oTable = $("table").dataTable({ ... your settings ... });
//redraws the table
oTable.fnDraw();

Event backgrid:rendered does not work - Backgrid.js

I try to use Backgrid.js. I have some grid (I just take server-mode example).
This library successfully built a grid for me. But I want map some cells to their equivalent. For example, I have "region_id" column. I want map region_id -> region_name. To complete this task, I subscribed to the event backgrid:rendered.
var grid = new Backgrid.Grid({
/////
collection: issues
});
grid.on('backgrid:rendered', function(g) {
$('tr').each(function (i, row) {
var $row = $(row);
console.log("Q");
});
});
But I get a fail. There is no iterating over rows of my table. But these rows exist in table. What is the problem?
Verify that both of the following is true:
you make a call to grid.render() method
issues variable refers to non-empty collection at the time of rendering
Unfortunately Backgrid fires the rendered event before the header, footer and the table itself are actually on the screen.
So when your event gets triggered there are no rows in DOM yet.
I solved my problem by calling my code after the
grid.render().$el
statement. After this table should be in DOM. At least header row was and that was all I needed.
I am stuck with old version of Backgrid 0.2.6. So bare in mind that my answer is from that perspective.

How to update ZK Grid values from jQuery

I have three Tabs and in each tab, I have a Grid.
The data for each Grid is coming from a database, so I am using rowRenderer to populate the Grids. The following code is common for all three Grids:
<grid id="myGrid1" width="950px" sizedByContent="true" rowRenderer="com.example.renderer.MyRowRenderer">
The rows are constructed from Doublebox objects. The data is populated successfully.
The Problem:
I need to handle multiple-cell editing on the client side. The editing is done via mouse-clicking on a particular cell and entering a value.
As example let's say that the user edits first cell on the first row and the value should be
propagated to all other cells on the same row and in all three Grids (so also the two Grids which the user currently does not see, because they are in tabpanes).
I am using jQuery to do this value propagation and it works OK.
I am passing the jQuery as follows:
doublebox.setWidgetListener(Events.ON_CHANGING, jQuerySelectors);
doublebox.setWidgetListener(Events.ON_CHANGE, jQuerySelectors);
This makes it possible to change the value in 1 cell and the change is instantly (visually) seen in all other cells filtered by jQuery selectors.
The problem is that the value is visually distributed to all the cells, but when I try to save the Grid data back to the database, the background values are the old ones.
I am assuming that ZK-Grid component is not aware that jQuery changed all the cell values. Nevertheless if I manually click on a cell that already has the NEW value (enter/leave/change focus) when I save the grid the NEW value is correct in that particular cell. Maybe that's a hint how can I resolve this.
Code of how I extract the Grid values:
Grid tGrid = (Grid) event.getTarget().getFellow("myGrid1");
ListModel model = tGrid.getModel();
MyCustomRow tRow = (MyCustomRow)model.getElementAt(i);
The model for my Grid is a List of MyCustomRow:
myGrid1.setModel(new ListModelList(List<MyCustomRow> populatedList));
I have a couple of assumptions, but whatever I have tried, hasn't worked. I have in mind that jQuery events and ZK-Events are different and probably isolated in different contexts. (Although I have tried to fire events from jQuery and so on..)
Do you have any suggestions? As a whole is my approach correct or there's another way to do this? Thanks for your time in advance!
Your problem is exactly what you are expecting.
Zk has it's own event system and do not care about your jq,
cos it's jq and zk don't observ the DOM.
The ways to solve your problem.
Use the "ZK-Way":
Simply listen at server-side and chage things there.
I am not sure if not selected Tabs
are updateable, but I am sure you could update the Grid
components on the select event of the Tab.
Fire an zk-event your self:
All you need to know, is written in the zk doc.
Basically, you collect your data at client side, send
an Event to the server via zAu.send() extract the
data from the json object at serverside and update your Grids
I would prefer the first one, cos it's less work and there should not be
a notable difference in traffic.
I post the solution we came up with:
This is the javascript attached to each Doublebox in the Z-Grid
//getting the value of the clicked cell
var currVal = jq(this).val();
//getting the next cell (on the right of the clicked cell)
objCells = jq(this).parents('td').next().find('.z-doublebox');
// if there's a next cell (returned array has length) - set the value and
// fire ZK onChange Event
if (objCells.length) {
zk.Widget.$(jq(objCells).attr('id')).setValue(currVal);
zk.Widget.$(jq(objCells).attr('id')).fireOnChange();
} else { //otherwise we assume this is the last cell of the current tab
//So we get the current row, because we want to edit the cells in the same row in the next tabs
var currRow = jq(this).parents('tr').prevAll().length;
//finding the next cell, on the same row in the hidden tab and applying the same logic
objCellsHiddenTabs = jq(this).parents('.z-tabpanel').next().find('.z-row:eq(' + currRow + ')').find('.z-doublebox');
if (objCellsHiddenTabs.length) {
zk.Widget.$(jq(objCellsHiddenTabs).attr('id')).setValue(currVal);
zk.Widget.$(jq(objCellsHiddenTabs).attr('id')).fireOnChange();
}
}
The java code in the RowRenderer class looks something like this:
...
if (someBean != null) {
binder.bindBean("tBean", someBean);
Doublebox box = new Doublebox();
setDefaultStyle(box);
row.appendChild(box);
binder.addBinding(box, "value", "tBean.someSetter");
...
private void setDefaultStyle(Doublebox box) {
box.setFormat("#.00");
box.setConstraint("no negative,no empty");
box.setWidth("50px");
String customJS = ""; //the JS above
//this is used to visually see that you're editing multiple cells at once
String customJSNoFireOnChange = "jq(this).parents('td').nextAll().find('.z-doublebox').val(jq(this).val());";
box.setWidgetListener(Events.ON_CHANGING, customJSNoFireOnChange);
box.setWidgetListener(Events.ON_CHANGE, customJS);
}
What is interesting to notice is that ZK optimizes this fireOnChange Events and send only 1 ajax request to the server containing the updates to the necessary cells.

Categories

Resources