├── .gitignore ├── LICENSE ├── README.md └── angular-export.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | node_modules 28 | 29 | # Optional npm cache directory 30 | .npm 31 | 32 | # Optional REPL history 33 | .node_repl_history 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # angular-export 2 | Angular directive for exporting and downloading JSON data into a CSV file 3 | 4 | ## Demo 5 | Demo is running in [Plunker here.](http://embed.plnkr.co/gtJeThGwByl0lv5GvF1l/). 6 | 7 | ## Usage 8 | 9 | Include the module in your 10 | 11 | ```ngModule.controller(myApp, ['export.csv']) ``` 12 | 13 | Create a link in your HTML and add required attributes 14 | 15 | ```Export Data ``` 16 | 17 | ## Attributes 18 | 19 | ### export-data 20 | #### *Array: Required* 21 | This contains the array of objects you want to download as csv. It must be a array of objects. e.g 22 | 23 | ```asnwers = [{Header1: Column1_1, Header2: Column1_2, Header3: Column1_3}, {Header1: Column2_1, Header2: Column2_2, Header3: Column2_3}]``` 24 | 25 | ### export-filename 26 | #### *String: Required* 27 | This is the name of the file to download. If it's not provided, the file name will be in the format `Export_Current_Date`; 28 | 29 | ### export-title 30 | ####*String: Optional* 31 | This is the title included inside the CSV download. An example CSV with a title is shown below 32 | 33 | CSV Title goes here 34 | 35 | Header1, Header2, Header3, 36 | Column1_1, Column1_2, Column1_3, 37 | Column2_1, Column2_2, Column2_3 38 | 39 | ### export-keys 40 | #### *Array: Optional* 41 | This is an optional array of what keys you want to extract from your data. The export will only contain these keys. 42 | ```Export Data ``` 43 | 44 | Header1, Header3, 45 | Column1_1, Column1_3, 46 | Column2_1, Column2_3 47 | 48 | ### export-headers 49 | #### *Array: Optional* 50 | By default, the CSV headers are the keys of all the objects you want to export. But you wan override them. The headers must be the same length as the data or the keys you want from the data. 51 | 52 | ```Export Data ``` 53 | 54 | Answer1, Answer2, Answer3, 55 | Column1_1, Column1_2, Column1_3, 56 | Column2_1, Column2_2, Column2_3 57 | -------------------------------------------------------------------------------- /angular-export.js: -------------------------------------------------------------------------------- 1 | angular 2 | .module('export.csv', []) 3 | .directive('export', function() { 4 | return { 5 | restrict: 'AE', 6 | scope: { 7 | data: '=exportData', 8 | title: '=exportTitle', 9 | keys: '=exportKeys', 10 | headers: '=exportHeaders', 11 | filename: '=exportFilename' 12 | }, 13 | link: function(scope, el, attrs) { 14 | el.bind('click', function() { 15 | var data = scope.data; 16 | var title = scope.title; 17 | var keys = scope.keys; 18 | var headers = scope.headers; 19 | var filename = scope.filename; 20 | 21 | if (data && !Array.isArray(data)) throwError("Data must be a valid javascript array"); 22 | if (keys && !Array.isArray(keys)) throwError("Keys must be a valid javascript array"); 23 | if (headers && !Array.isArray(headers)) throwError("Headers must be a valid javascript array"); 24 | 25 | // Remove any angular added keys 26 | var json_data = angular.toJson(data); 27 | data = JSON.parse(json_data); 28 | if (!data.length) throwError("No data available to export"); 29 | 30 | // Get keys & headers to be exported 31 | if (!keys) { 32 | var sample_data = data[0]; 33 | keys = Object.keys(sample_data); 34 | } 35 | if (headers && (headers.length != keys.length)) { 36 | throwError("Headers must be the same length as the " + (keys ? "keys": "data") + " to export"); 37 | } else if (!headers) { 38 | headers = convertToUppercase(keys); 39 | } 40 | 41 | data = filterArrayKeys(data, keys); 42 | 43 | 44 | ////////////////////////// 45 | //// Export Functions //// 46 | ////////////////////////// 47 | 48 | var csv = ''; 49 | if (title) { 50 | csv += title + '\r\n\n'; 51 | } 52 | csv += headers.join(",") + '\r\n'; 53 | 54 | for (var i = 0; i < data.length; i++) { 55 | var row = ""; 56 | for (var index in data[i]) { 57 | row += '"' + data[i][index] + '",'; 58 | } 59 | row.slice(0, row.length - 1); 60 | csv += row + '\r\n'; 61 | } 62 | 63 | if (csv == '') { 64 | throwError("Invalid Data"); 65 | } 66 | 67 | if (!filename) filename = "Export " + getDate(); 68 | filename = filename.replace(/ /g, "_"); 69 | var uri = 'data:text/csv;charset=utf-8,' + escape(csv); 70 | var link = document.createElement("a"); 71 | link.href = uri; 72 | link.style = "visibility:hidden"; 73 | link.download = filename + ".csv"; 74 | 75 | document.body.appendChild(link); 76 | link.click(); 77 | document.body.removeChild(link); 78 | 79 | 80 | ///////////////////////// 81 | /// Utility Functions /// 82 | ///////////////////////// 83 | 84 | function throwError(message) { 85 | throw message; 86 | return; 87 | } 88 | 89 | function filterArrayKeys(array, keys) { 90 | var result = []; 91 | if (!array.length || !keys.length) return result; 92 | for (var i = 0; i < array.length; i++) { 93 | var array_object = array[i]; 94 | var new_object = {}; 95 | for (var j = 0; j < keys.length; j++) { 96 | var key = keys[j]; 97 | var value = array_object[key]; 98 | new_object[key] = value; 99 | } 100 | result.push(new_object); 101 | } 102 | return result; 103 | }; 104 | 105 | function convertToUppercase(array) { 106 | var result = []; 107 | for (var i = 0; i < array.length; i++) { 108 | var key = array[i]; 109 | result.push(key.charAt(0).toUpperCase() + key.slice(1)); 110 | } 111 | return result; 112 | } 113 | 114 | function getDate() { 115 | var monthNames = [ 116 | "January", "February", "March", 117 | "April", "May", "June", "July", 118 | "August", "September", "October", 119 | "November", "December" 120 | ]; 121 | 122 | var date = new Date(); 123 | var day = date.getDate(); 124 | var monthIndex = date.getMonth(); 125 | var year = date.getFullYear(); 126 | 127 | return day + ' ' + monthNames[monthIndex] + ' ' + year; 128 | } 129 | }); 130 | } 131 | }; 132 | }); 133 | --------------------------------------------------------------------------------