On non-ajax tables it works fine.
Another thing is that the actions column probably shouldn't be on the export result by default, since the user doesn't normally want the text of some buttons on the exportation.
Damn. You're right. I do think making the export work for AJAX tables would be A LOT of work and basically involve wither rewriting the functionality or coding an alternative one just for the AJAX tables.
Will check and come back to you.
Thanks!
I'm just going to close this up for the time being to keep the place smaller, its been added to this list https://github.com/Laravel-Backpack/CRUD/issues/285
I've given this some thought, and I can't find a non-breaking solution. I guess this just needs to be a documented caveat of AjaxDataTables. ANOTHER documented caveat, until we rewrite ajaxdatatables and switch to it entirely.
I was just doing some datatables work and came across this, havent tested anything but had a thought.
search() but returns a json object. Maybe search() does this already? I havent checked.list.blade.php add exportOptions: {
columns: [':visible'],
format: {
body: function ( data, row, column, node ) {
// ACCESS JSON MODEL BASED OFF ROW AND COL
return result;
}
}
}
Thoughts?
Hi @b8ne ,
Hmm... sounds like a very interesting solution. I'd love it if it works. I'll schedule time to prototype it - see if it works. Thank you, I'll reopen the issue for this.
Cheers!
This is actually an issue with dataTables as well. We had a solution for it. See issue #714
If someone submits a PR, I suggest reopening this issue 😄
Per comment I've reopened.
Hi guys,
Following up on this, I concluded that search() does return a JSON, so bene's solution wouldn't provide better performance than a regular AJAX call. In the end, in order to export all rows, you'll need all rows :-)
So I think the simplest solution to this is the best - when picking how many rows are shown on page, have an "All" option. This would be a very slow page for huge dbs, obviously, but it would provide intuitivity for the Export buttons:
I've already pushed this solution into dev - https://github.com/Laravel-Backpack/CRUD/commit/ef863f1c05b983dd1c52f406281b741e95cc1b25, so I'll close this issue. Please let me know if you don't agree by reopening the issue and commenting.
Thanks! Cheers!
@tabacito this was something we discussed in the gitter channel today actually, and i had suggested that perhaps a new button be included called "export" so instead of just exporting all visible, it exports all the data by calling a new URL that forces a download. Thoughts?
The problem with an "All" button is that it might break the browser (IE was infamous for crashing on large datasets, I doubt that Edge is any better and although it seems that FireFox and Chrome cope, it's still silly).
Is there a way to do the export with the data without having to send it to the client to render?
Well, I am curious how to get this work as well :D
@AbbyJanke that's totally an option. If someone doesn't like DataTable's export buttons, he can always create a button called "Export", that does whatever he wants it to do... In most custom settings, in fact, I think that's faster than bending DataTables export to your will.
@lloy0076 - true. It couls be pretty hit-and-miss for millions of entries, because of some browsers. Can't test in IE/Edge myself but it wouldn't surprise me :-) I don't think there's a way without rendering - the problem isn't actually the rendering, it's the fact that it needs all that information onpage, since the files are generated with JavaScript. So the ajax call still needs to be made, for ALL entries... Come to think about it, that would be a problem for a PHP script too. If the DB is large, it would still take a lot of time to generate the file. So you'd need a "loading" spinner...
I think exporting millions of entries is a bit beyond the scope of Backpack. Sure, it would be great to have it, but I don't see how we can do that with the tools at hand. We could choose to code an export functionality ourselves, and it would be top-notch, with backend rendering not front-end, but it would be a huge effort. I think that can come in v4 or v5, when we decide to ditch DataTables altogether. I expect we'll outgrow it at some point, and I bet we can code something simpler and better using Vue or Angular.
@tabacitu said:
I expect we'll outgrow it at some point, and I bet we can code something simpler and better using Vue or Angular.
Something better could be written in both Vue or Angular - true. I'm not sure an Angular version would be simpler though.
@CHOMNANP it's now launched, so a composer update should get it for you.
I know a few people have come across the issue of not exporting more than the current page, my solution was to override the exportData function in datatables, then pass in the All page size to fetch the data.
@if ($crud->exportButtons())
// fix export
$.fn.DataTable.Api.register( 'buttons.exportData()', function ( options ) {
if ( this.context.length ) {
var data = table.ajax.params();
// set length to all
data.length = -1;
var jsonResult = $.ajax({
url: "{!! url($crud->route.'/search') . '?' . Request::getQueryString() !!}",
method: 'POST',
data: data,
async: false
});
var headings = $("#crudTable thead tr th")
.map(function() {
return this.innerText;
}).get();
return {
body: jsonResult.responseJSON.data,
header: headings
};
}
});
@endif
This needs to be defined before the datatable is initialised. I've not passed this onto the testers yet, but initial tests by me look to be exporting all data correctly
@Spodnet that sounds great!! Let me know what your testers find - if this works as expected, I’d love to have it as default.
@Spodnet what happened to your solution - did you end up using it as-is? My tests show that there are still problems with this:
start - if you were on a subsequent page it started from there; easy fix below;So right now, this doesn’t look usable to me. I’m not sure a 100% solution with DataTables is even possible - I think the best we can do is move the export functionality to PHP. That will would allow us to make huge files fast, then deliver them to the user. That’s a lot of work, but… I don’t see any other way.

// force export buttons to pull in all filtered entries, not just the current page
$.fn.DataTable.Api.register( 'buttons.exportData()', function ( options ) {
if ( this.context.length ) {
var data = crud.table.ajax.params();
// set length to all
data.length = -1;
data.start = 0;
var jsonResult = $.ajax({
url: crud.table.ajax.url(),
method: 'POST',
data: data,
async: false
});
var headings = $("#crudTable thead tr th")
.map(function() {
return this.innerText;
}).get();
return {
body: jsonResult.responseJSON.data,
header: headings
};
}
});
Most helpful comment
The problem with an "All" button is that it might break the browser (IE was infamous for crashing on large datasets, I doubt that Edge is any better and although it seems that FireFox and Chrome cope, it's still silly).
Is there a way to do the export with the data without having to send it to the client to render?