管理画面などでよく見るCSVエクスポート機能ですが、たいていはサーバーサイドでCSVファイルを生成してブラウザにダウンロードさせる、という方法で実装されていると思います。 今回はクライアントサイドで編集したデータをダウンロードする必要があったため、クライアントで完結してCSVファイルを出力する方法を調べてみました。
ポイント
実装例(AngularJS Service)
(function() { 'use strict'; angular .module('app') .service('CsvExporter', CsvExporter); /** @ngInject */ function CsvExporter($window) { this.export = function(object, keys) { // Serialize a header. var content = keys.join(',') + "\n"; // Serialize rows. angular.forEach(object, function(properties){ var row = ''; angular.forEach(keys, function(key, index){ if (index != 0) { row += ','; } if (properties[key]) { row += properties[key]; } }); content += (row + "\n"); }); // Convert text to blob object with Blob API. var blob = new Blob([ content ], { "type" : "text/csv" }); // For Internet Expolorer if ($window.navigator.msSaveBlob) { $window.navigator.msSaveBlob(blob, "export.csv"); // For other browsers } else { var link = $window.document.getElementById("csv_exporter"); if (link == null) { link = $window.document.createElement("a"); link.setAttribute("id", "csv_exporter"); link.setAttribute("style", "display:none;"); link.setAttribute("download", "export.csv"); } link.setAttribute("href", $window.URL.createObjectURL(blob)); link.click(); } }; } })()
DOM操作(a要素の追加)
- AngularJSではDirectiveの利用が推奨されますが、今回はファイル出力のために一時的にa要素を追加するため直接DOMを操作しています。 (ただし、$window Serviceを通してdocumentを参照するようにしています。)
- angular.element(jQuery/jqLite)を利用した場合は下記のように記述できます。
var link = angular.element("#csv_exporter"); if (link.length == 0) { link = angular.element("<a>"); link.attr("id", "csv_exporter"); link.attr("style", "display:none;"); link.attr("download", "export.csv"); } link.attr("href", $window.URL.createObjectURL(blob)); link[0].click();