Reputation: 11
I am using a table similar to datatables.net (it is not the same, but very similar) in an angular 12 project.
I need to populate the table with data like:
Id | Name | Action |
---|---|---|
0 | John | Delete |
1 | Conn | Delete |
The "Delete" action is a button that looks like a link and it would delete the current row.
When the user comes to the table for first time it needs to be empty. With a button the user imports data from a csv file.
Id | Name | Action |
---|
In the html component the table looks like this:
<table data-table="tt__table">
</table>
<input type="button" value="Import" (click)="importData()" />
When I import the data from csv in typescript I have something like:
ngAfterViewInit(): void {
let options = {
data: {
headings: ["Id", "Name", "Actions"],
rows: [
{
data: ["", "", ""]
}
]
}
};
this.tableElement = document.querySelector('[data-table=\"tt__table\"]') as Element;
this.table = new Table(this.tableElement, options);
}
...
importData(): void{
let importedData = {
"type": 'csv',
"data": '0,John,<button data-toggle="tt__btn" class="tt__btn-link (click)="deleteRow($event)">Delete</button>'
};
this.table.deleteAll();
this.table.import(importedData); // rows are created on the fly using vanilla js.
const tableButtons = document.querySelectorAll('[data-toggle=\"tt__btn\"]');
tableButtons.forEach(button => {
new Button(button, {})
});
}
deleteRow(event): void{
// Delete row.
}
The imported data looks fine after click on "Add" button:
Id | Name | Action |
---|---|---|
0 | John | Delete |
But when I click in "Delete" button it does not do anything.
I suspect the reason is that Angular cannot see the new DOM elements created because the HTML after clicking on "Add" button looks like this:
<tbody>
<tr>
<td data-content="0">0</td>
<td data-content="John">John</td>
<td data-content="Delete">
<button data-toggle="tt__btn" class="tt__btn-link" (click)="deleteRow($event)">Delete</button>
</td>
</tr>
</tbody>
But in other components where I use "(click)" angular directive, the final HTML does not show the "(click)" directive.
I am very new to angular, could you please help me how to solve this problem?
Upvotes: 0
Views: 716
Reputation: 11
I solved it by using Renderer2 to listen DOM events.
First I injected the renderer2 in constructor:
import { AfterViewInit, Renderer2, OnDestroy } from '@angular/core';
unlistener: () => void;
...
constructor(private renderer: Renderer2) {
...
}
Then I added a listener to renderer instance, which listen to DOM table "click" events and call to "deleteRow" function:
ngAfterViewInit(): void {
...
this.tableElement = document.querySelector('[data-table=\"tt__table\"]') as Element;
unlistener = this.renderer.listen(this.tableElement, "click", event =>
this.deleteRow(event));
this.table = new Table(this.tableElement, options);
...
}
"deleteRow" function catch the click events in the table and delete rows according to the button id (which has the user id):
deleteRow(event: any): void {
let userId: string = '';
let userToDelete: User;
let userIndex: number = -1;
if (event !== null && event !== undefined) {
if (event.target instanceof HTMLButtonElement) {
userId = event.target.id;
if (userId !== '') {
userToDelete = this.selectedUsers.find(u => u.userId === userId) as User;
if (userToDelete !== null && userToDelete !== undefined) {
userIndex = this.selectedUsers.indexOf(userToDelete);
this.selectedUsers.splice(userIndex, 1);
this.updateTable();
}
}
}
}
}
In ngOnDestroy() hook add unlistener to stop listening DOM events:
ngOnDestroy(): void {
this.unlistener();
}
Thanks for your replies, specially to @Mohamed Babei, his answer shed the light to my research.
This solution is based on Four ways of listening to DOM events in Angular (Part 3: Renderer2.listen) article.
Upvotes: 1
Reputation: 493
You can not bind angular events this way so you need to render your data in table angular way for example useing '''*ngFor''' or if you want go your way use addEventListener( click ) after rendering content
Upvotes: 0