EDITOR- Traversing table's data once initilized or updated
EDITOR- Traversing table's data once initilized or updated
agustin_garcia
Posts: 17Questions: 0Answers: 0
Hello,
I'm creating a series of tables with Editor, which work perfectly. However, I'd like to be able to traverse through each row (in a specific column) in a certain table, add up each value and reflect the total in another place of my page.
I tried to follow the example for "fnFooterCallback" found at the examples section, however it's giving me the following error: "DataTables warning (table id = 'inc_items_short'): Cannot reinitialise DataTable." if I use any of the call back functions (because the table has been already created and displayed)
If using Editor, What would be the right approach to capture any change on the table's data and reflect something accordingly?
Thanks in advance
I'm creating a series of tables with Editor, which work perfectly. However, I'd like to be able to traverse through each row (in a specific column) in a certain table, add up each value and reflect the total in another place of my page.
I tried to follow the example for "fnFooterCallback" found at the examples section, however it's giving me the following error: "DataTables warning (table id = 'inc_items_short'): Cannot reinitialise DataTable." if I use any of the call back functions (because the table has been already created and displayed)
If using Editor, What would be the right approach to capture any change on the table's data and reflect something accordingly?
Thanks in advance
This discussion has been closed.
Replies
Glad to hear that you are enjoying using Editor thus far :-)
I think using Editor should actually make little difference to how the column sum is done - you are right in using fnFooterCallback (or fnDrawCallback), but it sounds like your are trying to reinitialise the DataTables.
What I would suggest is using the http://datatables.net/plug-ins/api#fnGetColumnData plug-in in fnFooterCallback (just call this.fnGetColumnData(...)) and then sum the array if gives you back :-)
Allan
However, now I'm facing this issue that ONLY if I DO leave the alert sentence there -see code extract, it traverses correctly and gathers the whole data.
But if I remove that sentence (which I need to), it doesn't gets any data from the table,, like if it was empty (even the actual CRUD table shows rows data as expected.
Not sure if it has to do with the obtrusive/non-ubtrusive model, with the time with the data is actually populated (and displayed) in the CRUD table view, or what else.
I thought $document).ready was executed as the very last instruction after everything else has been processed.
Can you guide on this, or should I look into a different forum? Not sure if this behavior is related with DataTables Editor or is a more basic event handling thing
Code snipet:
$(document).ready( function() {
var dataTable = $('#inc_items').dataTable();
alert(dataTable);
var aoData = dataTable.fnGetData();
var recipientList = new CategoryCollection();
// Loop over each value in the array.
$.each(aoData, function(intIndex, objRow){
if (recipientList.exists(objRow.recipient, objRow.category)) {
recipientList.increase(objRow.recipient, objRow.category, objRow.payment_amount);
console.debug("UPDATE - Recipient: " + objRow.recipient + " | Category: " + objRow.category + " | Amount: " + objRow.payment_amount);
} else{
recipientList.insert(objRow.recipient, objRow.category, objRow.payment_amount);
console.debug("NEW - Recipient: " + objRow.recipient + " | Category: " + objRow.category + " | Amount: " + objRow.payment_amount);
}
});
recipientList.print();
} );
If you could link me to your page that would be really helpful (a page showing the problem you are having).
Allan
This page is still on my local environment, and I'm afraid pasting the code here will make it too large.
Let me know if there is a place to upload it or if you want me to past the ~1000 lines here
Allan
I'm trying to replicate my code into the live.datatables.net.
Mean time I'm attaching a functional extract of my whole code, please notice that:
1) if I enable both alerts ( alert("Income OK"); and alert("CC Expenses OK"); ), only the first one is displayed and only the INCOME summary table (on dashboard tab) is populated.
2) If I disable the "Income OK" alert, and the "CC Expenses OK" alert is left enabled, then only the "EXPENSES" summary table is populated in the Dashboard tab.
3) If I disable both nothing is written to the INCOME nor to the EXPENSES tables.
Hope you can provide some guidance.
@import "css/demo_page.css";
@import "css/jquery.dataTables.css";
@import "css/dataTables.tabletools.css";
@import "css/dataTables.editor.css";
@import "css/demo_table.css";
@import "css/jquery-ui.css";
<!-- Load the tabber code -->
document.write('.tabber{display:none;}<\/style>');
var tabberOptions = {
'manualStartup':true,
'onLoad': function(argsObj) {
if (argsObj.tabber.id == 'demotab') {
alert('Finished loading demotab!');
}
},
'onClick': function(argsObj) {
var t = argsObj.tabber;
var id = t.id;
var i = argsObj.index;
var e = argsObj.event;
if (id == 'demotab') {
return confirm('Swtich to '+t.tabs[i].headingText+'?\nEvent type: '+e.type);
}
if (t.tabs[i].headingText == 'Dashboard') {
$("#income_by_category").val($("#totalAmount").val());
}
},
'addLinkId': true
};
$(document).ready( function() {
var dataTable = $('#inc_items').dataTable();
//alert("Income OK");
var aoData = dataTable.fnGetData();
var incomeList = new CategoryCollection();
var fGrossIncome = 0.0;
var type = "Gross Income";
$.each(aoData, function(intIndex, objRow){
if (incomeList.exists(objRow.recipient, type, objRow.category)) {
fGrossIncome += parseFloat(objRow.payment_amount);
incomeList.increase(objRow.recipient, type, objRow.category, objRow.payment_amount);
} else{
fGrossIncome += parseFloat(objRow.payment_amount);
incomeList.insert(objRow.recipient, type, objRow.category, objRow.payment_amount);
}
});
var totalAmount = parseFloat(0.0);
incomeList.forEach( function(objItem) {
totalAmount += parseFloat(objItem.amount);
$("#income_summary > tbody").append(""+ objItem.name + "" +
""+ type + "" +
""+ objItem.category + "" +
""+ objItem.amount + "" +
"");
});
$("#income_summary > tbody").append("TOTAL:"+ totalAmount + "");
var ccDataTable = $('#exp_credit_cards').dataTable();
//alert("CC Expenses OK");
var aoData = ccDataTable.fnGetData();
var expenseList = new CategoryCollection();
var fCreditCards = 0.0;
var type = "Credit Cards";
var category = "Credit Cards";
$.each(aoData, function(intIndex, objRow){
if (expenseList.exists(objRow.debtor, type, category)) {
fCreditCards += parseFloat(objRow.payment_amount);
expenseList.increase(objRow.debtor, type, category, objRow.payment_amount);
} else{
fCreditCards += parseFloat(objRow.payment_amount);
expenseList.insert(objRow.debtor, type, category, objRow.payment_amount);
}
});
var totalCCAmount = parseFloat(0.0);
expenseList.forEach( function(objItem) {
totalCCAmount += parseFloat(objItem.amount);
$("#expense_summary > tbody").append(""+ objItem.name + "" +
""+ type + "" +
""+ objItem.category + "" +
""+ objItem.amount + "" +
"");
});
$("#expense_summary > tbody").append("TOTAL:"+ totalCCAmount + "");
} );
Dashboard
Income
Name
Type
Category
Total
Middle Col
Expenses
Debtor
Type
category
Total
Income
Monthly Income
From/To
Recipient
Category
Amount
Estimated?
Periodicity
Next Discount Date
Automatic Tracking
Bill Reminder
Recipient ID
Family linked
Income Type
Memo
Monthly Expenses
Credit Cards
Bank
Debtor Name
Credit Card Name
Credit Limit
Current Balance
Interest Rate
Debtor ID
Min. Payment
To Capital
To Interest
Due Date
Bill Reminder
Family Linked
Automatic Tracking
Memo
Min Rate (%)
Cut date
Associated Promotions?
Total Promotions ($)
tabberAutomatic(tabberOptions);
I tried to replicate my code as suggested on "http://live.datatables.net", unfortunately I wasn't able to, because the references to other libraries.
Please let me know if by looking at the code I attached above helps to delve into what's happening, otherwise I'll start working on uploading this code into a live server.
Thanks again
I uploaded the app to a live site: http://a4enterprise.com/tabber/financial_dashboard.html
However, It continues without working, now It's giving me also the error: DataTables warning: JSON data from server could not be parsed.
I tested the connection with a simple script (http://a4enterprise.com/tabber/connection/connection.php), the connection to the DB is being gathered successfully, but no luck when calling the Datatables script.
I've looked into Firebug, but isn't showing anything.
I uploaded into Datatables Debug (debug code: icuhav ), where is triggering the error:
Fatal error
Call to undefined function date_create_from_format()
DTFormat.class.php on line 35.
Hope you can provide guidance here
I think you need to either update your PHP install to 5.3 or the current 5.4, or the function date_create_from_format needs to be replaced with something that will work with older versions of PHP.
Allan
I removed the "date_create" error and setup a new test page:
http://a4enterprise.com/tabber/temp.html.
The same behavior remains, if I remove the sentence "alert("TEST");" the script doesn't seem to get anything via dataTable() and displays nothing.
But if I display the alert, everything works just fine and the records from the Datatable are traversed correctly.
The code on the above link is very simplified now, just to prove the issue. Hope this time we can get to something, whether it's an integration issue or if I'm doing something wrong.
Thanks for your support
[code]
$(document).ready( function() {
var dtObj = $('#test').dataTable();
var aoData = dtObj.fnGetData();
[...]
[/code]
that will run only when the page is first loaded, and since you are loading the data for the DataTable through Ajax (i.e. it is asynchronous) this code will run before the data has been loaded.
It works with an alert in there, since that is blocking and allowing the Ajax request to complete.
So I'd suggest using fnFooterCallback as I suggested to calculate your column sum. That will be calculated on every draw - see for example: http://datatables.net/release-datatables/examples/advanced_init/footer_callback.html
Allan
I didn't decide to use the fnFooterCallback approach because it was giving me an error like shown below, which I didn't understand how to address.
As per your suggestion, I just changed the code to include fnFooterCallback, but it keeps triggering the cannot reinitialize error.
"
Datatables warning (table id = 'test'): Cannot reinitialise DataTable.
To retrieve the Datatables object for this table, pass no arguments or see the docs for bRetrieve and bDestroy
"
You can see the code at: http://a4enterprise.com/tabber/temp2.html
I'm not entirely sure how where the fnFooterCallback code is on that page - I don't actually see any DataTables on it. However, my guess is that (like the error says) you are trying to initialise the DataTables twice with different parameters. You can only initialise a table once - so your footer callback code needs to go in with the rest of your table configuration.
Allan
The call to fnFooterCallback is on the Editor's generated table.test.js, I customized that call and it's gathering the table's data after it's populated (which is correct).
Based on your feedback, I realized that I'm pursuing for something different: What I need is to gather the data from "aaData" (from 8-10 Datatables I have on the same page), do some operations and write it to separate "regular" html summary tables, which can be defined either prior or after the Datatables have been populated.
I'm not too familiar with the Asynchronous/Synchronous model of Javascript, so I guess my problem reduces to that.
If you have any example or can provide any guidance on how to accomplish this, I'd appreciate it.
Otherwise I thank you again for your support you have provided here.
> If you have any example or can provide any guidance on how to accomplish this
Yes have a close look at my example fnFooterCallback :-)
Allan
I think I haven't been able to explain what I'm pursuing here, or to understand how to use your example
1) I have two files:
a)table.test.js -> which was generated by Editor (and calls the other auto-generated Editor files)
b)test2.html -> Includes .js file and a call to the Datatable table
2) I define a global variable in test2.html object called hashSavings = new Hashtable()
3) If I include the "fnFooterCallback" call and example code in the .js file, it gathers the rows' data and put it into my object (savingsHash), no issues here since I can travers what was put there
4) But, If I try to traverse the same object in the main html, it's size is shown as 0, and no actual data seems to be stored there.
5) I understand the data is being stored, so we go back to the sync/async thing, because if I display the alert() again just before trying to traverse the object (in the .html), I can get the data that was put in it during the call to the "fnFooterCallback"
1. Alter table.test.js to include an fnFooterCallback function such as this in the DataTables initialisation:
[code]
"fnFooterCallback": function () {
console.log("footer callback");
}
[/code]
2. Check that on your browser's Javascript console you see the text "footer callback" appear for every draw.
3. Pick up the fnGetColumnData plug-in I mentioned before from the plug-ins page.
4. Use fnGetColumnData (this.fnGetColumnData(...) inside the callback) in the fnFooterCallback function to get an array of data for the column you want.
5. Loop over the data array, sum and write the sum to the footer's cells as required.
Allan
That part is working fine, what I haven't accomplished yet, it the second part of my needs, which somehow I described above:
I have several Datatables in my page, and I need them all to be loaded and do some post-processing after loading (or changing).
With the objects generated during each datatable´s summarization, I'm trying to build up a dashboard.
My issue is that the standard tables used in the Dashboard, are being built before all the Datatables finish their own processing, but I don't think this has anything to do with Datatables, but with the sync/async that I still need to delve into.
thanks for your support
1. Use fnServerData to intercept the Ajax call and manipulate the data that is returned from the server before DataTables does its thing with it.
2. Use mDataProp as a function to manipulate the data for each row - http://datatables.net/blog/Orthogonal_data
3. Use fnRender for simple manipulation of column data (making HTML links etc). A bit like mDataProp as a function, but less flexible.
Allan
I just added my fnServerData code after the oTableTools section generated by EDITOR, it was somehting like this:
$('#example').dataTable( {
...
...
"oTableTools": {
"sRowSelect": "single",
"aButtons": [
{ "sExtends": "editor_create", "editor": editor },
{ "sExtends": "editor_edit", "editor": editor },
{ "sExtends": "editor_remove", "editor": editor }
]
},
"fnServerData": function ( sSource, aoData, fnCallback ) {
$.getJSON( sSource, aoData, function (json) {
/* My code*/
$.each(json.aaData, function(intIndex, objRow){
insertSummaryRecord(...);
});
fnCallback(json);
} );
} );