How to export table data in Angular
Exporting table data to CSV or JSON lets users take data out of web applications for further processing. As the creator of CoreUI with over 10 years of Angular experience since 2014, I’ve implemented data export for reporting dashboards where users need to analyze data in Excel or share it with colleagues. The standard approach builds the file content as a string, creates a Blob, and triggers a download via a temporary anchor element. This works without any server-side code or third-party libraries.
Export table data to a CSV file.
import { Component } from '@angular/core'
import { CommonModule } from '@angular/common'
@Component({
selector: 'app-exportable-table',
standalone: true,
imports: [CommonModule],
template: `
<button (click)="exportCsv()">Export CSV</button>
<button (click)="exportJson()">Export JSON</button>
<table>
<thead>
<tr><th>Name</th><th>Email</th><th>Role</th></tr>
</thead>
<tbody>
<tr *ngFor="let row of rows">
<td>{{ row.name }}</td>
<td>{{ row.email }}</td>
<td>{{ row.role }}</td>
</tr>
</tbody>
</table>
`
})
export class ExportableTableComponent {
rows = [
{ name: 'Alice Smith', email: '[email protected]', role: 'Admin' },
{ name: 'Bob Johnson', email: '[email protected]', role: 'User' },
{ name: 'Carol White', email: '[email protected]', role: 'Editor' }
]
exportCsv() {
const headers = ['Name', 'Email', 'Role']
const csvRows = [
headers.join(','),
...this.rows.map(row =>
[row.name, row.email, row.role]
.map(v => `"${v.replace(/"/g, '""')}"`)
.join(',')
)
]
this.download(csvRows.join('\n'), 'users.csv', 'text/csv')
}
exportJson() {
const json = JSON.stringify(this.rows, null, 2)
this.download(json, 'users.json', 'application/json')
}
private download(content: string, filename: string, type: string) {
const blob = new Blob([content], { type })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = filename
a.click()
URL.revokeObjectURL(url)
}
}
The CSV builder wraps values in double quotes and escapes internal quotes. Blob creates an in-memory file. createObjectURL generates a temporary download URL. Clicking the anchor triggers the browser download dialog. revokeObjectURL frees the memory afterward.
Exporting with Column Selection
Let users choose which columns to export.
import { Component } from '@angular/core'
import { CommonModule } from '@angular/common'
import { FormsModule } from '@angular/forms'
@Component({
selector: 'app-selective-export',
standalone: true,
imports: [CommonModule, FormsModule],
template: `
<div class="export-options">
<label *ngFor="let col of allColumns">
<input type="checkbox" [(ngModel)]="col.selected" />
{{ col.label }}
</label>
<button (click)="export()" [disabled]="selectedColumns.length === 0">
Export CSV
</button>
</div>
<table>
<thead>
<tr>
<th *ngFor="let col of selectedColumns">{{ col.label }}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of rows">
<td *ngFor="let col of selectedColumns">{{ row[col.key] }}</td>
</tr>
</tbody>
</table>
`
})
export class SelectiveExportComponent {
rows = [
{ name: 'Alice', email: '[email protected]', role: 'Admin', joined: '2024-01-15' },
{ name: 'Bob', email: '[email protected]', role: 'User', joined: '2024-03-10' }
]
allColumns = [
{ key: 'name', label: 'Name', selected: true },
{ key: 'email', label: 'Email', selected: true },
{ key: 'role', label: 'Role', selected: true },
{ key: 'joined', label: 'Join Date', selected: false }
]
get selectedColumns() {
return this.allColumns.filter(c => c.selected)
}
export() {
const cols = this.selectedColumns
const header = cols.map(c => c.label).join(',')
const csvRows = this.rows.map(row =>
cols.map(c => `"${(row as any)[c.key]}"`).join(',')
)
const content = [header, ...csvRows].join('\n')
const blob = new Blob([content], { type: 'text/csv' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = 'export.csv'
a.click()
URL.revokeObjectURL(url)
}
}
Checkboxes let users toggle columns. selectedColumns derives from the column configuration. The export uses only selected columns dynamically. This is useful for tables with many columns where users only want a subset.
Adding Export with Filtered Data
Export only the currently visible (filtered) rows.
exportFilteredData() {
const dataToExport = this.filteredRows.length > 0 ? this.filteredRows : this.rows
const headers = Object.keys(dataToExport[0]).join(',')
const csvRows = dataToExport.map(row =>
Object.values(row).map(v => `"${v}"`).join(',')
)
const content = [headers, ...csvRows].join('\n')
const blob = new Blob([content], { type: 'text/csv' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = `export-${new Date().toISOString().split('T')[0]}.csv`
a.click()
URL.revokeObjectURL(url)
}
Exporting filtered rows gives users exactly what they see in the table. The filename includes today’s date for easy identification. Object.keys and Object.values work dynamically for any data shape.
Best Practice Note
This is the same export pattern we use in CoreUI Angular admin templates for data reporting features. Always handle special characters in CSV - commas, quotes, and newlines inside values must be escaped. For large datasets exceeding ~50,000 rows, generate files on the server to avoid freezing the browser. Add a loading state during large exports. For Excel format (.xlsx), use the xlsx npm package which handles Excel-specific formatting. Always add the export date to filenames to help users track when data was captured.



