├── .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 |
--------------------------------------------------------------------------------