mui-datatables icon indicating copy to clipboard operation
mui-datatables copied to clipboard

Download CSV downloads all data instead of just current page data in server side mode

Open ssword opened this issue 6 years ago • 16 comments

In server-side mode, download CSV will only download data that is available to render the current page. It is possible to use a different source for CSV creation so that we can provide full data in the CSV file.

Expected Behavior

Given an option to provide custom data while Creating CSV.

Current Behavior

Only use data that is queried for current page rendering.

Steps to Reproduce (for bugs)

Your Environment

Tech Version
Material-UI "@material-ui/core": "^3.9.0"
MUI-datatables "mui-datatables": "^2.0.0-beta-1"
React "react": "^16.6.0"
browser Chrome
etc

ssword avatar Apr 05 '19 00:04 ssword

hey @ssword what would you propose in terms of changes? Let's see some examples in terms of API changes

gregnb avatar Apr 13 '19 16:04 gregnb

@gregnb, thanks for answering my issue. I have checked the code, perhaps we can add another option in downloadOptions called customCSVdata. Then when serverside option is true, and customCSVdata is not null, we will replace data with customCSVdata.

    const options = {
      filter: false,
      search: false,
      count: rowCount,
      serverSide: true,
      downloadOptions: { 
          filename: 'eventTable.csv',
          // new API change added here
          customCSVdata: fullServersideData,
      },
      rowsPerPage: rowsPerPage,
      rowsPerPageOptions: [10, 20, 50],
      selectableRows: false,
      elevation: 0,
      },
    };

I am not good at javascript, perhaps we need to make CSV creation process an asynchronous process, then the changes maybe big.

ssword avatar Apr 16 '19 18:04 ssword

I think instead you could just add an option that skips the code that runs after options.onDownload. If the API (server-side) downloads a file, no need for the rest of that code to run and download another file. Otherwise, if you just want to pass the data through to the table, you could use onDownload.

Avd6977 avatar Jun 05 '19 21:06 Avd6977

How can I download external CVS files?

ronaiza-cardoso avatar Aug 27 '19 09:08 ronaiza-cardoso

You have to put that logic into the onDownload prop and return false so this download doesn't happen (or else you'll just get a blank file)

Avd6977 avatar Aug 27 '19 12:08 Avd6977

+1 Does any one have an example on how to download the csv server side, instead of just the first page in table ? @ssword @gabrielliwerant @Avd6977 @gregnb

thbl avatar Jul 31 '20 07:07 thbl

@thbl - @Avd6977 is right, this is how I do it:

onDownload: (buildHead, buildBody, columns, data) => {
    props.download_from_server(); // this makes a REST call to the server and downloads the data
    return false;
}.

I used a library called downloadjs to download the results from my call. That library is a little old though, not sure if there are any newer solutions.

patorjk avatar Jul 31 '20 13:07 patorjk

@patorjk okay so you just make mui-datatables return false onDownload, and handle REST & Download call else where ?

thbl avatar Jul 31 '20 14:07 thbl

Yes, inside of the onDownload option you invoke the code that will lead to the CSV being downloaded from your server. You return false to prevent the table from creating the CSV itself.

patorjk avatar Jul 31 '20 14:07 patorjk

@patorjk got it thanks 👍

thbl avatar Jul 31 '20 14:07 thbl

I was in the process of implementing an onDownload function that requests all the pages of my data from the server. I would then use the buildBody function to write it to the export file. But this requires an async ajax call, and onDownload is synchronous. So we'd need onDownload to be asynchronous, or buildBody to accept a Promise.

carlin-q-scott avatar Nov 25 '20 18:11 carlin-q-scott

Any chance of having an async option?

vsachini avatar Mar 19 '21 05:03 vsachini

As an easier alternative to making onDownload asynchronous, how about passing in options and downloadCSV as additional arguments to onDownload?

This would allow access to options.downloadOptions.filename, which would be a big help.

It would also be a big help to have access to the existing downloadCSV code.

d-a-s avatar Aug 26 '21 14:08 d-a-s

Any updates on this?

mahesh1996 avatar Dec 20 '21 06:12 mahesh1996

********************************************** THIS IS JUST A HACK ******************************************** In onDownload, you can write a dispatch to get the data from the server side. then check a condition if the data is available in the reducer. if data is available, build the csv. else wait for a few seconds... trigger download button click and return false. this worked for me

let filtrInterval; // initialize this

onDownload: (buildHead, buildBody, columns, data) => {
  dispatch(getServerSideData(searchText, filterList, sortOrder));
  if (ServerSideData) {
    return buildHead(columns) + buildBody(ServerSideData);
  } else {
    if (filtrInterval) clearInterval(filtrInterval);
    filtrInterval = setInterval(function () {
      document
        .querySelectorAll('[data-testid="DownloadCSV-iconButton"]')[0]
        .click();
      clearInterval(filtrInterval);
    }, 1500);
    return false;
  }
},

alextelias avatar Aug 08 '22 07:08 alextelias