Topic: Dynamic columns table
JackZeled0n pro asked 6 years ago
It is possible to generate columns dynamically with mdbTable ?, I want to create a component where can dynamically generate the columns that are in the tbody tag from the data the data that I send, something similar to this angular material image. Thank you very much in advance!!
Damian Gemza staff answered 6 years ago
Dear @JackZeled0n
There's no built-in feature from our tables to add new column.
But you can use Angular Renderer2 class to create dynamic elements.
Please take a look at the below code:
.html:
<div class="container my-5">
<table mdbTable>
<thead>
<tr>
<th *ngFor="let head of headElements" scope="col">{{head}} </th>
</tr>
</thead>
<tbody>
<tr mdbTableCol *ngFor="let el of elements" #tablerow>
<th scope="row">{{el.id}}</th>
<td>{{el.first}}</td>
<td>{{el.last}}</td>
<td>{{el.handle}}</td>
</tr>
</tbody>
</table>
</div>
<button mdbBtn color="primary" (click)="addRow()">Add new row</button>
.ts:
@ViewChildren('tablerow') tableRow: QueryList<ElementRef>;
elements: any = [
{id: 1, first: 'Mark', last: 'Otto', handle: '@mdo'},
{id: 2, first: 'Jacob', last: 'Thornton', handle: '@fat'},
{id: 3, first: 'Larry', last: 'the Bird', handle: '@twitter'},
];
headElements = ['ID', 'First', 'Last', 'Handle'];
constructor(private el: ElementRef, private renderer: Renderer2) {
}
addRow() {
this.tableRow.toArray().forEach((elem: any) => {
const el = this.renderer.createElement('td');
const text = this.renderer.createText('Dynamic element');
this.renderer.appendChild(el, text);
this.renderer.appendChild(elem.nativeElement, el);
})
}
Best Regards,
Damian
Damian Gemza staff answered 6 years ago
Dear @JackZeled0n
I don't think that using pagination on dynamic elements is possible but you could try to use the following scenario:
1) Add elements dynamically,
2) Use the pagination button
3) If table row fill logical requirement:
"i+1 >= mdbTablePagination.firstItemIndex && i < mdbTablePagination.lastItemIndex"
remove the d-none
class, else add d-none
class
I don't know if this scenario will work for you, but you may try.
Best Regards,
Damian
JackZeled0n pro answered 6 years ago
Thank you very much for your prompt response, I did the tests with a table and it worked to a certain extent (for what I want to do), then I came up with the following question, is it possible to use the pagination with the implementation you suggested?
Following the code you gave me, I made this implementation that appears in the image, with test data, but I have no idea how to add the pagination.
My ultimate goal is to create datatables in a dynamic way, with all its functions of ordering, searching, page, etc.
.ts
@ViewChild(MdbTableDirective) mdbTable: MdbTableDirective;
@ViewChild(MdbTablePaginationComponent) mdbTablePagination: MdbTablePaginationComponent;
@ViewChildren("tablerow") tableRow: QueryList<ElementRef>;
elements: any = [
{ id: 1, first: "Mark", last: "Otto", handle: "@mdo" },
{ id: 2, first: "Jacob", last: "Thornton", handle: "@fat" },
{ id: 3, first: "Larry", last: "the Bird", handle: "@twitter" }
];
headElements = ["Id", "First", "Last", "Handle"];
findText: string = "";
previo: string;
@HostListener("input") oninput() {
this.mdbTablePagination.searchText = this.findText;
this.buscarItems();
}
constructor(
private el: ElementRef,
private renderer: Renderer2,
private cdRef: ChangeDetectorRef
) {}
ngOnInit() {
this.mdbTable.setDataSource(this.elements);
this.elements = this.mdbTable.getDataSource();
this.previo = this.mdbTable.getDataSource();
}
ngAfterViewInit(): void {
this.mdbTablePagination.setMaxVisibleItemsNumberTo(2);
this.mdbTablePagination.calculateFirstItemIndex();
this.mdbTablePagination.calculateLastItemIndex();
this.cdRef.detectChanges();
this.headElements.forEach((value, index) => {
let i = 0;
this.tableRow.toArray().forEach((elem: any) => {
const el = this.renderer.createElement("td");
let text;
if (index === 2) {
text = this.renderer.createText(String(i));
} else {
text = this.renderer.createText(String(i + 2));
}
this.renderer.appendChild(el, text);
this.renderer.appendChild(elem.nativeElement, el);
i = i + 1;
});
});
}
buscarItems() {
const prev = this.mdbTable.getDataSource();
if (!this.findText) {
this.mdbTable.setDataSource(this.previo);
this.elements = this.mdbTable.getDataSource();
}
if (this.findText) {
this.elements = this.mdbTable.searchLocalDataBy(this.findText);
this.mdbTable.setDataSource(prev);
}
}
metodo(value, event): string {
if (value === "Id") return "id";
if (value === "First") return "first";
if (value === "Last") return "last";
if (value === "Handle") return "handle";
}
.html
<div class="container my-5">
<div class="row">
<div class="col-12">
<div class="in input-group md-form form-inline form-sm form-2 pl-0 mt-5">
<i class="fa fa-search mt-3 black-text" aria-hidden="true"></i>
<input class="form-control w-75 ml-3" type="search" placeholder="Buscar" aria-label="Buscar"
[(ngModel)]="findText" id="search">
</div>
</div>
</div>
<table mdbTable #tableEl="mdbTable" hover="true" small="true" bordered="true" striped="true">
<thead>
<tr>
<th [mdbTableSort]="elements" *ngFor="let head of headElements" [sortBy]="metodo(head, th)" #th scope="col">{{head}} </th>
</tr>
</thead>
<tbody>
<tr mdbTableCol *ngFor="let el of elements; let i = index" #tablerow>
</tr>
</tbody>
<tfoot class="grey lighten-5 w-100">
<tr>
<td colspan="5">
<mdb-table-pagination [tableEl]="tableEl" paginationAlign="" [searchDataSource]="elements">
</mdb-table-pagination>
</td>
</tr>
</tfoot>
</table>
JackZeled0n pro answered 6 years ago
FREE CONSULTATION
Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.
Resolved
- User: Pro
- Premium support: No
- Technology: MDB Angular
- MDB Version: 7.5.1
- Device: Laptop
- Browser: Chrome
- OS: Windows 10
- Provided sample code: No
- Provided link: No