I am trying to make table configurable. Before that I am making demo component through which I can make a my own configurable table.
I want to pass few things to my table like, column names
and data
.
Column Name I want to pass like this:
headers = [ {name: 'Sr.No'}, {name: 'name', dataType: 'text'}, {name: 'mobile', dataType: 'number'}, {name: 'date', dataType: 'date'}, {name: 'Action'} ];
the dataType
above states that this column will have input type text
when is editable
, same for number
and date
as well.
I want to show input boxes based on this values, but in <td>
I am not able to check this dataType
key. I tried this:
html
<table class="row-border border-1 table"> <thead> <tr> <th *ngFor="let head of headers">{{head.name}}</th> </tr> </thead> <tr *ngFor="let tableData of data; let i=index"> <td>{{i+1}}</td> <ng-container *ngIf="tableData.isEditable; else viewable"> <div *ngIf="tableData.dataType ==='text'"> <input type="text"> </div> <div *ngIf="tableData.dataType ==='date'"> <input type="date" > </div> <div *ngIf="tableData.dataType ==='number'"> <input type="date"> </div> </ng-container> <td> <button *ngIf="!tableData.isEditable" (click)="onEdit(tableData)">Edit</button> <button *ngIf="!tableData.isEditable">Delete</button> <button *ngIf="tableData.isEditable" (click)="onSave(tableData)">Update</button> </td> <ng-template #viewable> <td>{{tableData.name}}</td> <td>{{tableData.mobile}}</td> <td>{{tableData.date}}</td> </ng-template> </tr> </table>
ts file
headers = [ {name: 'Sr.No'}, {name: 'name', dataType: 'text'}, {name: 'mobile', dataType: 'number'}, {name: 'date', dataType: 'date'}, {name: 'Action'} ]; data = [ {id:1, name: 'sam', mobile: '8788888888', date: '20/11/2021', isEditable: false}, {id:2, name: 'joy', mobile: '9788888888', date: '22/11/2021', isEditable: false}, ] onEdit(data) { this.data.map((item) => { item.isEditable = data.id === item.id; }) } onSave(data) { data.isEditable = false; }
Is there any way, so that I can check the column dataType and based on that I am able to show that input box in that cell of row when I click on edit
button? Thanks in advance!!!
Advertisement
Answer
Oh dear lord have I spent much time in my past to create beautiful and editable tables. I know how annoying this can be so I took my time and looked at your example.
Here is a quick and very dirty version I took your example.
You need to be able to map the headers to the properties of the data otherwise you can’t identify which column represents which values as it is currently hardcoded in your example.
headers = [ {name: 'Sr.No'}, {name: 'name', dataType: 'text', mappedProperty: 'name'}, {name: 'mobile', dataType: 'number', mappedProperty: 'mobile'}, {name: 'date', dataType: 'date', mappedProperty: 'date'}, {name: 'Action'}];
Furthermore you need to iterate through the headers in the view template to get the mappedProperty and to figure out which dataType it has.
Here is the possible solution:
<table class="row-border border-1 table"> <thead> <tr> <th *ngFor="let head of headers">{{head.name}}</th> </tr> </thead> <tr *ngFor="let tableData of data; let i=index"> <td>{{i + 1}}</td> <ng-container *ngIf="tableData.isEditable; else viewable"> <ng-container *ngFor="let head of headers"> <ng-container *ngIf="head.mappedProperty"> <td> <input [type]="head.dataType" [(ngModel)]="tableData[head.mappedProperty]"> </td> </ng-container> </ng-container> </ng-container> <td> <button *ngIf="!tableData.isEditable" (click)="onEdit(tableData)">Edit</button> <button *ngIf="!tableData.isEditable">Delete</button> <button *ngIf="tableData.isEditable" (click)="onSave(tableData)">Update</button> </td> <ng-template #viewable> <td>{{tableData.name}}</td> <td>{{tableData.mobile}}</td> <td>{{tableData.date}}</td> </ng-template> </tr> </table>
And here is the onEdit function. In my opinion you just need to toggle isEditable. But I am unsure what you were trying in the example so sorry for any misunderstand:
onEdit(tableData: any) { tableData.isEditable = !tableData.isEditable; }
Have fun with the example and if you need any help let me know.
Important: This is way to much to write for each table. Do yourself a favore and abstract it into a component and reuse it. Some interface like this should work. And the code is quite similar to the current.
<my-table-component [columnDefinition]="headers" [rows]="data"></my-table-component>