Jquery DataTable Reinitialization - javascript

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.

Related

DataTable not filtering newly inserted data properly

For reference, I am using DataTable.js version 1.10.21 and DataTables Select version 1.3.1
I have created a DataTable with a "Status" column that can be updated. This column also has a filter on it. The filter works perfectly after initial load of the table but after a cell in the status column has been changed, the filter doesn't seem to be seeing the updated data but, instead, still filters on the old data.
This is the js that is being used to update a particular cell in the status column:
NOTE: We've simplified the example to eliminate code that isn't an issue.
var row = document.getElementById("user-id-" + userId);
statusColumn = row.children[4];
statusColumn.innerText = "inactive";
setTimeout(function(){
$('.dataTable').DataTable().reload();
},2000);
I have attempted to use the reload(), draw(), and re-initializing the entire table using dataTable(). None of functions allows the table to filter correctly with the new value. The filter does work but it filters based on the old value that no longer exists in the table.
Below are two screenshots as a visual example.
1st screenshot: Me looking at newly loaded table and me filtering on the status "active.
I am then going to change Aaron McClendon (first row) to "inactive".
2nd screenshot: Me searching on the status "active" again. Aaron should no longer show up since he is now "inactive" but as you can see he does show in the "active" status filter yet his status has been changed to "inactive".
Filtering to other statuses and coming back does not change the results and the only way to begin filtering correctly on the updated data is by reloading the page.
Newly loaded table while filtering on the active status
After updating Aaron McClendon and filtering on the active status
You need to set the data of the cell using the api: https://datatables.net/reference/api/cell().data()
It's difficult to give a detailed answer since you didn't post any of the html markup or enough of your javascript, but based on what you provided, it's probably something like this:
var table = $('.dataTable').DataTable();
var row = document.getElementById("user-id-" + userId);
var statusColumn = row.children[4];
var cell = table.cell( statusColumn );
cell.data( "inactive" ).draw();

Reinitialize tabulator on same DOM element with new data and different column configuration

I am working with tabulator (jQuery plugin). I want to re-initialized the tabulator on same div element with different column config and data dynamically. Below is the sample div and script that I am using. I feel that, tabulator not allow to change the column configuration once its render.
$("#sample_div").tabulator(tabulator_display_config);
//initialize and apply tabulator
$("#sample_div").tabulator("setData", table_data.Data);
//load data into the table
You can try to redraw the tabulator after the new initialization
$("#sample_div").tabulator("setData", table_data.Data);
$("#sample_div").tabulator("redraw", true);
I use the destroy function and reinitialize tabulator. It works for me.
$("#sample_div").tabulator("destroy");
$("#sample_div").tabulator(tabulator_display_config);
$("#sample_div").tabulator("setData", table_data.Data);
If you just want to change your column configuration and keep your sorting you could get your current sorting using the getSorters function before updating the columns and data and then resorting:
var sort = $("#sample_div").tabulator("getSorters");
$("#sample_div").tabulator(tabulator_display_config);
$("#sample_div").tabulator("setData", table_data.Data);
$("#sample_div").tabulator("setSort ", sort);

Pagination on filtered rows — Resetting original data set — jQuery Datatables

This is a problem I had with jQuery Datatables that I really don't know why it is happening in the first place!
I have multiple select elements which all filters the original data set. I do the filtering logic on the select change event.
This my Datatables init (using state saving, from the documentation) :
var table = $('#orders-listing').DataTable({
bStateSave: true,
bFilter:true,
paging: true,
bPaginate:true,
language: { url: /* Language File URL */ },
fnStateSave: function(oSettings, oData){
localStorage.setItem('DataTables_'+window.location.pathname, JSON.stringify(oData));
},
fnStateLoad: function(oSettings){
return JSON.parse(localStorage.getItem('DataTables_'+window.location.pathname));
}
});
And this is my filtering logic on the select change event:
$('.filter-select').on('change', function() {
$.fn.dataTable.ext.afnFiltering.push(
function(settings, data, dataIndex) {
// Some logic, return a boolean, wether we keep the row being processed or not.
}
);
table.draw();
$.fn.dataTable.ext.afnFiltering.pop();
});
Now, the filtering works fine. The rows, pagination links, everything changes accordingly.
But, once I click on the 2nd link on the pagination links, the original dataset returns.
Example: I had 200 rows in the first place, after filtering, it was reduced to 150 (So 50 rows were filtered, and removed from the original dataset), then once I click on the second link on the pagination, the original dataset returns, with the first 200 rows.
What am I missing here ? What is causing the original dataset to return when paginating ?
Any help is greatly appreciated. Thanks.
You're doing $.fn.dataTable.ext.afnFiltering.pop() immediately after drawing the table with draw() which removes your custom filter and it will no longer be applied if table is sorted, page is changed, etc.
Try adding $.fn.dataTable.ext.afnFiltering.pop() before $.fn.dataTable.ext.afnFiltering.push() to remove previous custom filter only on filter change but before adding a new filter.

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
});

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