I'm submitting a ... (check one with "x")
[ ] bug report => search github for a similar issue or PR before submitting
[X ] feature request
[ ] support request => Please do not submit support request here, post on Stackoverflow or Gitter
Can you implement export of the datatable as a csv please?
Thanks
Explicitly mentioned as out of scope.
https://swimlane.gitbooks.io/ngx-datatable/introduction/architecture.html
You're able to build this yourself with what ngx-datatable gives you
Sorry for asking
I agree that csv export has been a must feature for datatables lately. If you are not planning build it, would you give an example or any tips how to implement it with ngx-datatable. I think that would be really helpful for many developers 馃憤
Here is a first attempt (only using ngx-datatable for 1 month and Angular 4 for 2 months so bear with me please).
Be sure to install angular2-csv, first:
npm install --save angular2-csv
<ngx-datatable
#dataTable
class="light striped"
[rows]="rows"
...
</ngx-datatable>
@ViewChild('dataTable') public dataTable: DatatableComponent;
...
exportAsCSV() {
const columns: TableColumn[] = this.dataTable.columns || this.dataTable._internalColumns;
const headers =
columns
.map((column: TableColumn) => column.name)
.filter((e) => e); // remove column without name (i.e. falsy value)
const rows: any[] = this.dataTable.rows.map((row) => {
let r = {};
columns.forEach((column) => {
if (!column.name) { return; } // ignore column without name
if (column.prop) {
let prop = column.prop;
r[prop] = (typeof row[prop] === 'boolean') ? (row[prop]) ? 'Yes'
: 'No'
: row[prop];
} else {
// special cases handled here
}
})
return r;
});
const options = {
fieldSeparator : ',',
quoteStrings : '"',
decimalseparator: '.',
showLabels : true,
headers : headers,
showTitle : false,
title : 'Report',
useBom : true,
};
return new Angular2Csv(rows, 'report', options);
}
_Disclaimer
I'm using internal properties (_internalColumns) since the getter wasn't giving me any data (??). I guess we can achieve way better by using other methods of TableColumn but it should take care of simple use cases.
This is NOT production-ready code whatsoever, use it at your own risk 馃挜!_
some definitive solution to export to CSV ?? I miss jquery data-table T.T !!!
Has anyone successed to implement this grid download in csv facility ?
There's a big issue with @guillaumegarcia13's code, as it just uses the row's data and not the datatable's templates. most of the data (atleast in my projects) is objects and is used in complex ways in templates.
example -
<ngx-datatable-column prop="PropName" name="Prop Name">
<ng-template let-value="value" ngx-datatable-cell-template>
{{value.Type | TypeDisplayNamePipe}} ({{value.Desc}})
</ng-template>
</ngx-datatable-column>
Also - the code doesn't support nested properties - "PropName.PropName2" in the column.prop.
Added a portion to deal with that -
import { DatatableComponent, TableColumn } from "@swimlane/ngx-datatable";
import { Angular5Csv } from 'angular5-csv/Angular5-csv';
export function exportAsCSV(dataTable: DatatableComponent) {
const columns: TableColumn[] = dataTable.columns || dataTable._internalColumns;
const headers =
columns
.map((column: TableColumn) => column.name)
.filter((e) => e); // remove column without name (i.e. falsy value)
const rows: any[] = dataTable.rows.map((row) => {
let r = {};
columns.forEach((column) => {
if (!column.name) { return; } // ignore column without name
if (column.prop) {
let prop = column.prop.toString();
let value = getNestedPropertyValue(row, prop);
r[prop] = (typeof value === 'boolean') ? (value ? 'Yes' : 'No') : value;
} else {
// special cases handled here
}
})
return r;
});
const options = {
fieldSeparator : ',',
quoteStrings : '"',
decimalseparator: '.',
showLabels : true,
headers : headers,
showTitle : false,
title : 'Report',
useBom : true
};
return new Angular5Csv(rows, 'report', options);
}
function getNestedPropertyValue(object: any, nestedPropertyName: string) {
var dotIndex = nestedPropertyName.indexOf(".");
if (dotIndex == -1) {
return object[nestedPropertyName];
} else {
var propertyName = nestedPropertyName.substring(0, dotIndex);
var nestedPropertyNames = nestedPropertyName.substring(dotIndex + 1);
return getNestedPropertyValue(object[propertyName], nestedPropertyNames);
}
}
I got to the point of rendering the cell-templates and taking the text off of the html element.
I created a new component -
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'dynamic-template',
template: `
<ng-template
[ngTemplateOutlet]="template"
[ngTemplateOutletContext]="context">
</ng-template>
`
})
export class TemplateComponent {
@Input() template;
@Input() context;
}
and the new code to use it :
import { DatatableComponent, TableColumn } from "@swimlane/ngx-datatable";
import { Angular5Csv } from 'angular5-csv/Angular5-csv';
import { TemplateComponent } from "./components/common/template.component";
import { ComponentFactoryResolver, Injector } from "@angular/core";
export function exportAsCSV(dataTable: DatatableComponent, resolver: ComponentFactoryResolver, injector: Injector) {
const columns: TableColumn[] = dataTable.columns || dataTable._internalColumns;
const headers =
columns
.map((column: TableColumn) => column.name)
.filter((e) => e); // remove column without name (i.e. falsy value)
const rows: any[] = dataTable.rows.map((row) => {
let r = {};
columns.forEach((column) => {
if (!column.name) { return; } // ignore column without name
var prop
var propValue;
if (column.prop) {
prop = column.prop.toString();
propValue = getNestedPropertyValue(row, prop);
}
if (column.cellTemplate) {
r[column.name] = getRenderedTemplateText(column.cellTemplate, propValue, row, resolver, injector);
} else {
r[column.name] = (typeof propValue === 'boolean') ? (propValue ? 'Yes' : 'No') : propValue;
}
});
return r;
});
const options = {
fieldSeparator: ',',
quoteStrings: '"',
decimalseparator: '.',
showLabels: true,
headers: headers,
showTitle: false,
title: 'Report',
useBom: true
};
return new Angular5Csv(rows, 'report', options);
}
function getRenderedTemplateText(template, value, row, resolver: ComponentFactoryResolver, injector: Injector) {
const factory = resolver.resolveComponentFactory(TemplateComponent);
const component = factory.create(injector);
component.instance.template = template;
component.instance.context = { value: value, row: row };
component.changeDetectorRef.detectChanges();
return component.location.nativeElement.textContent.trim();
}
function getNestedPropertyValue(object: any, nestedPropertyName: string) {
var dotIndex = nestedPropertyName.indexOf(".");
if (dotIndex == -1) {
return object[nestedPropertyName];
} else {
var propertyName = nestedPropertyName.substring(0, dotIndex);
var nestedPropertyNames = nestedPropertyName.substring(dotIndex + 1);
return getNestedPropertyValue(object[propertyName], nestedPropertyNames);
}
}
When there's a template connected to a column, I create a new TemplateComponent with the right template and context, render it and take the text, If not I use the old code to just get the value from the row based on the nested property.
I created the context based on the data I needed
component.instance.context = { value: value, row: row };
If you use more data, add it to the context too.
Also I changed it from r[prop] to r[column.name] as I want the csv to reflect what's on screen, there's an issue with columns with the same name atm which you can fix by appending _# at the end of names or looking more into Angular5Csv's options or code.
I might make this class a service so I can inject the dependencies directly, but this works great for me.
I have a better PRACTICAL solution for this.
In most of the cases, the
datais comming fromAPI.
So, it would be great if we convert the data to csv directly.
Yes, It is possible...
Step 1 : npm install @ctrl/ngx-csv
Step 2 : module.ts
```
@NgModule({
declarations: [
...
...
...
],
imports: [
...
CsvModule,
...
]
})
Step 3 : **component.html**
CSV
```
Hope you find this solution helpfull :)
Most helpful comment
I agree that csv export has been a must feature for datatables lately. If you are not planning build it, would you give an example or any tips how to implement it with ngx-datatable. I think that would be really helpful for many developers 馃憤