angular17
- I need to create a custom library for my angular project.
- I need to implement a data grid like ag-grid without using any external packages/libraries like ag-grid.
- I have created this data grid with pagination, sorting, searching, column filtering.
- I would like to create a dynamic component or something like that which will accept any cell renderer component and bind it in the data grid table.
- The cell renderer can be any it will be passed along with the column defs.
- It should then render it’s template content in the cell of a table.
- Below is what I have tried so far.
Grid view component is part of the library and a standalone component:
<table [class]="tableStyle">
<thead class="header-row">
<tr [class]="headerStyle">
<ng-container *ngFor="let header of gridData.colDefs; let i = index">
<th [class.frozen-column]="gridData.frozenColumn === header.field">
<span [ngStyle]="{
cursor: header.field !== 'Action' ? 'pointer' : 'default'
}" (click)="header.field !== 'Action' && sortData(header.field)">
{{ header.field }}
<span style="float: right" *ngIf="sortColumn === header.field && header.field !== 'Action'">
{{ sortDirection === "asc" ? "▲" : "▼" }}
</span>
</span>
</th>
</ng-container>
</tr>
<tr *ngIf="gridData.searchableColumns">
<ng-container *ngFor="let header of gridData.colDefs; let i = index">
<td [class.frozen-column]="gridData.frozenColumn == header.field">
<input id="{{ header }}" [class]="columnFilterCss" *ngIf="
gridData.searchableColumns &&
gridData.searchableColumns.includes(header.field) &&
header.field !== 'Action'
" type="text" [(ngModel)]="columnFilters[header.field]" (input)="applyColumnFilter(header.field)"
placeholder="Search {{ header.field }}" />
</td>
</ng-container>
</tr>
</thead>
<tbody>
<ng-container *ngIf="totalItems > 0; else noRecordsFound">
<tr [class]="rowStyle" *ngFor="let row of filteredData">
<ng-container *ngFor="let header of gridData.colDefs">
<td [class.frozen-column]="gridData.frozenColumn === header.field" *ngIf="header.field != 'Action'">
<!-- <span *ngIf="header.cellRenderer">
<easy-dynamic [component]="header.cellRenderer"></easy-dynamic>
</span>
<span [innerHTML]="
(header.field !== 'Action' ? row[header.field] : '')
| safeHtml
"></span> -->
<div *ngIf="header.cellRenderer">
<!-- <app-image-cell-renderer [value]="row[header.field]"></app-image-cell-renderer> -->
</div>
<div *ngIf="header.field !== 'Action' && !header.cellRenderer">
{{ row[header.field] }}
</div>
<td *ngIf="header.field === 'Action'" [class.frozen-column]>
<button *ngFor="let data of gridData.action" (click)="data.callbackFunc(row)" [class]="data.css">
<ng-container *ngIf="data.text; else iconOrImage">
{{ data.text }}
</ng-container>
<ng-template #iconOrImage>
<ng-container *ngIf="data.icon; else image">
<i [class]="data.icon"></i>
</ng-container>
<ng-template #image>
<img [src]="data.image" [class]="data.css" />
</ng-template>
</ng-template>
</button>
</td>
</ng-container>
</tr>
</ng-container>
<ng-template #noRecordsFound>
<tr>
<td style="text-align: center; font-size: x-large" [attr.colspan]="gridData.colDefs.length">
No records found
</td>
</tr>
</ng-template>
</tbody>
</table>
cell renderer is part of the mail application
export class ImageCellRendererComponent implements OnInit {
@Input() value: any;
displayValue: string = '';
ngOnInit(): void {
this.displayValue = this.value;
}
showDefault(event: any) {
event.target.src = '/assets/images/default-image.jpg';
}
}
//template
<div class="row">
<div class="col-lg-2">
<div>
<img [src]="displayValue" alt="" class="rounded-circle avatar-md" (error)="showDefault($event)" />
</div>
</div>
</div>
Column defs is passed from main application to the grid component in the library.
columnDefs: IColDefs[] = [
{ field: 'Id' },
{ field: 'Name', cellRenderer: ImageCellRendererComponent },
{ field: 'Designation' },
{ field: 'Department' },
];
New contributor
jaymin darji is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.