gregnb / mui-datatables

Datatables for React using Material-UI
MIT License
2.7k stars 931 forks source link

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

Open ssword opened 5 years ago

ssword commented 5 years ago

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
gregnb commented 5 years ago

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

ssword commented 5 years ago

@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.

Avd6977 commented 5 years ago

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.

ronaiza-cardoso commented 5 years ago

How can I download external CVS files?

Avd6977 commented 5 years ago

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)

thbl commented 4 years ago

+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

patorjk commented 4 years ago

@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.

thbl commented 4 years ago

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

patorjk commented 4 years ago

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.

thbl commented 4 years ago

@patorjk got it thanks 👍

carlin-q-scott commented 3 years ago

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.

vsachini commented 3 years ago

Any chance of having an async option?

d-a-s commented 3 years ago

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.

mahesh1996 commented 2 years ago

Any updates on this?

alextelias commented 2 years ago

** 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;
  }
},