Download data from Angular ngGrid as CSV

I have an Angular ngGrid on my page.  I want the user to be able to download a spreadsheet copy of the data.  Ideally I want the filtered copy of the data.

First - ngGrid CSV Export Plugin

First I tried the ngGrid plugin, CSV Export.  It worked fine until I threw 10,000 rows at it.  Then it would literally add time to my page load in the magnitude of 10 seconds.  Also, once I got over about 6,000 rows, clicking the CSV Export button would cause my page to crash.  (Using Chrome 26)

This technique relies on data urls.  Read more about those here:

This is no offense to the creator(s) of the CSV Export Plugin, just my experience as of this writing.

It's possible that a data URI will still work as per this example: http://stackoverflow.com/a/15690552/1804678

Second - download hyperlink

The second option I tried was to create a hyperlink that would download the data by calling a service (provided by node.js).  This is a fairly simple option, but it requires a duplicate service call to the one that loaded my grid in the first place; requires that I edit the service to support returning CSV; and will not give me the filtered rows of the grid.  Anywho, I added this to my html:

<a ng-href='/history/{{qs}}'>download spreadsheet</a>

And in my route (node.js):

exports.history = function(req, res) {
res.set({
'Content-Disposition' : 'attachment; filename="a.csv"',
'Content-Type' : 'text/csv'
});

res.send("\"a\",\"b\"\n1,2\n3,4"); // Hard coded example.
};

This works, but I'm still not really satisfied.

Third - mini form submit

This is a cool idea I found based on a stack overflow post.  Basically, form submit JSON from your $scope to a service.  This would be similar to the second option, but it uses a form in the html instead of a hyperlink. Also it is a post, so that you are actually posting the JSON data to the back end, convert the data there from json to CSV (using json2csv).  Then return the data as an "attachment".  You can't use the node/express "attachment" function since that takes a file, but you can mimic the attachment function by setting the headers yourself (also shown in the second option above).

This option works really well.

Here's the HTML:


<form action='/json2csv' method='post'>
<input type="hidden" name="json" value="{{mydata}}" />
<input type='submit' value="3. Download Spreadsheet"/>
</form>

And here's the server side node code:


exports.json2csv = function(req, res) {
var jsonObj = JSON.parse(req.body.json);
var fields = Object.keys(jsonObj[0]);
json2csv({
"data" : jsonObj,
"fields" : fields
}, function(err, csv) {
if (err)
console.log(err);
res.set({
'Content-Disposition' : 'attachment; filename="a.csv"',
'Content-Type' : 'text/csv'
});
res.send(csv);
});
};


Comments

  1. I tried the 3rd option, but i keep getting a '404 file or directory not found error'. I changed 'mydata' to my own json array. It can't seem to find '/json2csv' path.

    ReplyDelete
    Replies
    1. Did you add this line to your main js file? Like app.js or server.js?

      app.post('/json2csv', yourModule.json2csv);

      Delete
  2. Thanks for the page!

    Was trying CSV in ngGrid - but am getting 'undefined' errors from ln 42 and then
    from ln 57 (once 42 was commented out for testing). Seems like the plugin just isn't seeing anything.

    NgGrid is working just fine otherwise.

    Any thoughts on what to check?

    ReplyDelete
    Replies
    1. Hi David. Does your data have anything funky like null, quotes or commas in the data? I'd recommend trying to create a jsfiddle, plunker, or codepen. Sometime I find myself doing that. You can either, build up your example and add code until you find your issue, or you can paste your code in and tear stuff out until you find what it is. I few strategically placed breakpoints might help too.

      Delete

Post a Comment

Popular Posts