nggridify2
Version:
ng-gridify reimagined for Angular2+. Generic grid for angularJS with paging, sorting, the ability to export CSV and configurable content.
143 lines (123 loc) • 5.25 kB
text/typescript
import { OnInit, Input, Component, OnChanges } from '@angular/core';
import { ngGridifyData } from './ng-gridify.types';
import { NgGridifyService } from './services/ng-gridify.service';
({
selector: 'ng-gridify',
template: `
<h3>{{ gridData.Title }}</h3>
<p *ngIf="showError">{{ errorMessage }}</p>
<table *ngIf="!showError">
<colgroup>
<col *ngFor="let col of gridData.Columns;" width="{{col.Width}}">
</colgroup>
<tr>
<th *ngFor="let col of columnNames; let i = index; trackBy: trackByFn">
<a href="#" (click)="SortGrid(i)">{{col}}</a>
</th>
<th>
<button *ngIf="gridData.ExportEnabled" (click)="ExportDataToCSV()">Export</button>
</th>
</tr>
<tr
*ngFor="let row of gridData.Data
| SortPipe: sortByColumn : sortByAscending
| PagePipe: itemsPerPage : currentPage
">
<td *ngFor="let col of columnKeys;">
{{ngGridifyService.DeepValue(row, col)}}
</td>
<td>
<a href="#" (click)="gridData.ItemClick.Function(row)">{{gridData.ItemClick.Text}}</a>
</td>
</tr>
<tr>
<td [attr.colspan]="gridData.Columns.length+1">
Go to page:
<button *ngFor="let page of pages; let i=index" (click)="ChangePage(i+1)">{{i+1}}</button>
</td>
</tr>
</table>
`
})
export class ngGridifyComponent {
// The grid data that is passed into the component
()
gridData: ngGridifyData;
// These two really could do with being in a tuple instead of two arrays but contain references
// to the dynamic columns that have been provided to the component
columnNames: string[];
columnKeys: string[];
// All other local variables that control sorting and paging.
itemsPerPage: number = 99999;
currentPage: number = 1;
numberOfPages: number = 0;
pages: number[] = [];
sortByColumn: string = null;
sortByAscending: boolean;
errorMessage: string = 'Sorry! An error has occurred, and the data could not be rendered.';
// Flag used to display the grid or error message
showError: boolean = false;
constructor(private ngGridifyService: NgGridifyService) { }
// When starting up, we first look to see if we are getting data from a service or a JSON array
ngOnInit() {
if (this.gridData.DataUrl && this.gridData.DataUrl.length > 1) {
// DataUrl used
this.gridData.Data = [];
this.ngGridifyService.GetDataFromService(this.gridData.DataUrl)
.subscribe(response => {
this.gridData.Data = response;
this.SetupGrid();
}, error => {
this.errorMessage = (this.gridData.ErrorMessage != null) ? this.gridData.ErrorMessage : this.errorMessage
this.showError = true;
})
}
else if (this.gridData.Data && this.gridData.Data.length > 0) {
// Data directly injected
this.SetupGrid();
}
}
// When we have our data, we can set the items per page here aswell as the number
// of pages and create an array of these to bind to on the component.
SetupGrid () {
this.itemsPerPage = this.gridData.ItemsPerPage;
this.numberOfPages = Math.ceil(this.gridData.Data.length / this.itemsPerPage);
this.pages = Array(this.numberOfPages);
this.columnNames = this.gridData.Columns.map(e => e.DisplayValue);
this.columnKeys = this.gridData.Columns.map(e => e.Name);
this.sortByColumn = (this.gridData.SortBy) ? this.gridData.SortBy : (this.columnKeys[0]) ? this.columnKeys[0] : '';
this.sortByAscending = (this.gridData.SortByAscending != null) ? this.gridData.SortByAscending : true;
}
// When a column header is clicked, we can sort the grid, this is done by the sort pipe.
SortGrid (index: number) {
this.sortByAscending = !this.sortByAscending;
this.sortByColumn = this.columnKeys[index];
}
// Changes the users current page by passing the current page into the pagin pipe.
ChangePage (page: number) {
this.currentPage = page;
}
// Export function will be created here (currently only tested in Google Chrome)
// NOTE TO SELF : I'd like to rename the document that is being returned to the grid name.
ExportDataToCSV() {
// The content type needs to be set to allow it to be opened in numbers/excel/openofice
let csvContent = "data:text/csv;charset=utf-8,";
const cols = this.columnKeys;
// Setup the headers
csvContent += cols.join(",") + '\n';
// I'm sure there is a more efficient way to do this, but we basically loop over the items, match the requested columns
// push the result into a comma delimited string, with a new line on each row.
this.gridData.Data.map(item => {
csvContent += cols.map(column => this.ngGridifyService.DeepValue(item, column)).join(",") + '\n';
})
// Open the content in a new window
const encodedUri = encodeURI(csvContent);
window.open(encodedUri);
}
/* CURRENTLY RUNNING INTO ISSUES WITH THE ON CHANGE OF THE ARRAY THIS NEEDS WORK - IJP
ngOnChanges(changes: SimpleChanges) {
console.log(changes, '!');
this.SetupGrid();
}
*/
}