fnAddData very slow ?
fnAddData very slow ?
Arnaud
Posts: 2Questions: 0Answers: 0
Hello,
I really like this table component and its well detailed documentation.
Generally, I'm using dataTables with javascript array of objects because I want to separate model and view.
So, I retrieve a large array by ajax call (500+ lines), store it in a javascript module, then call my view which will create a dataTables. Then, each change will be reflected in my model (source).
For about a month, I have used a bad performance code (didn't know about aaData combined with mDataProp):
[code]
var table = $("#currentMods").dataTable({ ... });
table.fnClearTable();
$.each(produits, function(index, produit) {
table.fnAddData([ produit.produitCode, produit.produitLabel, produit.nomenclatureLabel ]);
});
[/code]
With less than 100 lines, this code worked great and it was fast, almost instant (alls test are made in Chrome, which has a good javascript engine).
Now, with about 500-600 lines, this same code takes between 10 seconds to several minutes (depending on my columns rendering).
In my next example, rendering is almost instant with aaData, but took about 1-2 minutes, so long that javascript engine might crash or asked if I want to kill process.
So, my conclusion is that fnAddData should never be used to build large tables.
And if I need to refresh all my tables because I got a new request from server, I just destroy and recreate.
[code]
modsTable = $("#currentMods").dataTable({
sScrollY : '500px', bSort: true, bPaginate: false, aaSorting: [],
aoColumnDefs: [
{
aTargets: [0], sType: "html", mDataProp: "name",
mRender: function (data, type, full) {
return Utils.htmlElement('a', { href: transformUrl(full[1]), target: '_blank' }, data);
}
},
{ aTargets: [1], sType: "numeric", mDataProp: "url", bVisible: false },
{
aTargets: [2], sType: "numeric", mDataProp: "installed",
mRender: function (data, type, full) {
if (type !== 'display') {
return data;
}
return Utils.htmlElement('input', { type: 'checkbox', name: full[0], checked: data, class: 'installed' });
}
},
{
aTargets: [3], sType: "numeric", mDataProp: "category",
mRender: function (data, type, full) {
if (type !== 'display') {
return data;
}
var options = '', html = '';
$.each(Category, function(index, category) {
options += Utils.htmlElement('option', { value: category.value, selected: category.value == data }, category.label);
});
html += Utils.htmlElement('select', { name: full[0], class: 'category' }, options);
html += Utils.htmlElement('span', { class: 'hide' }, data);
return html;
}
},
{
aTargets: [4], sType: "numeric", mDataProp: "notation",
mRender: function (data, type, full) {
if (type !== 'display') {
return data;
}
var options = '', html = '';
$.each(Notation, function(index, note) {
options += Utils.htmlElement('option', { value: note.value, selected: note.value == data }, note.label);
});
html += Utils.htmlElement('select', { name: full[0], class: 'notation' }, options);
html += Utils.htmlElement('span', { class: 'hide' }, data);
return html;
}
},
{
aTargets: [5], sType: "html", mDataProp: "url",
mRender: function (data, type, full) {
var html = '';
html += Utils.htmlElement('a', { class: 'edit' }, 'Edit') + ' ';
html += Utils.htmlElement('a', { class: 'delete' }, 'X');
return html;
}
}
],
aaData: mods
});
}
[/code]
I really like this table component and its well detailed documentation.
Generally, I'm using dataTables with javascript array of objects because I want to separate model and view.
So, I retrieve a large array by ajax call (500+ lines), store it in a javascript module, then call my view which will create a dataTables. Then, each change will be reflected in my model (source).
For about a month, I have used a bad performance code (didn't know about aaData combined with mDataProp):
[code]
var table = $("#currentMods").dataTable({ ... });
table.fnClearTable();
$.each(produits, function(index, produit) {
table.fnAddData([ produit.produitCode, produit.produitLabel, produit.nomenclatureLabel ]);
});
[/code]
With less than 100 lines, this code worked great and it was fast, almost instant (alls test are made in Chrome, which has a good javascript engine).
Now, with about 500-600 lines, this same code takes between 10 seconds to several minutes (depending on my columns rendering).
In my next example, rendering is almost instant with aaData, but took about 1-2 minutes, so long that javascript engine might crash or asked if I want to kill process.
So, my conclusion is that fnAddData should never be used to build large tables.
And if I need to refresh all my tables because I got a new request from server, I just destroy and recreate.
[code]
modsTable = $("#currentMods").dataTable({
sScrollY : '500px', bSort: true, bPaginate: false, aaSorting: [],
aoColumnDefs: [
{
aTargets: [0], sType: "html", mDataProp: "name",
mRender: function (data, type, full) {
return Utils.htmlElement('a', { href: transformUrl(full[1]), target: '_blank' }, data);
}
},
{ aTargets: [1], sType: "numeric", mDataProp: "url", bVisible: false },
{
aTargets: [2], sType: "numeric", mDataProp: "installed",
mRender: function (data, type, full) {
if (type !== 'display') {
return data;
}
return Utils.htmlElement('input', { type: 'checkbox', name: full[0], checked: data, class: 'installed' });
}
},
{
aTargets: [3], sType: "numeric", mDataProp: "category",
mRender: function (data, type, full) {
if (type !== 'display') {
return data;
}
var options = '', html = '';
$.each(Category, function(index, category) {
options += Utils.htmlElement('option', { value: category.value, selected: category.value == data }, category.label);
});
html += Utils.htmlElement('select', { name: full[0], class: 'category' }, options);
html += Utils.htmlElement('span', { class: 'hide' }, data);
return html;
}
},
{
aTargets: [4], sType: "numeric", mDataProp: "notation",
mRender: function (data, type, full) {
if (type !== 'display') {
return data;
}
var options = '', html = '';
$.each(Notation, function(index, note) {
options += Utils.htmlElement('option', { value: note.value, selected: note.value == data }, note.label);
});
html += Utils.htmlElement('select', { name: full[0], class: 'notation' }, options);
html += Utils.htmlElement('span', { class: 'hide' }, data);
return html;
}
},
{
aTargets: [5], sType: "html", mDataProp: "url",
mRender: function (data, type, full) {
var html = '';
html += Utils.htmlElement('a', { class: 'edit' }, 'Edit') + ' ';
html += Utils.htmlElement('a', { class: 'delete' }, 'X');
return html;
}
}
],
aaData: mods
});
}
[/code]
This discussion has been closed.
Replies
Simply pass false as the second parameter and then call fnDraw when the loop finishes. Blazing performance :-)
DataTables 1.10's new API does not do an automatic redraw (fnAddData does for backwards compatibility, but the new `row.add()` and `rows.add()` methods do not - in part for this reason).
Allan
On the same subject, fnDraw would greatly benefit from a parameter that only update one row and not the whole table. Update should be at least visually updated, even if filters and sort are not re-applied.
Currently, when I update a row, I disable redraw to avoid loosing my current table focus but then, I don't see what I have changed, I am forced to use jquery to do that job.
Allan