Reputation: 1995
I have several components that use basically the same table so I'm in the process of abstracting out that table. I have solved most of my dynamic table population needs but have yet to find a solution to the following.
In one of my table instances the rows need to be clickable. In the original table I simply added a click event in the row and had it call a function in my typescript file.
Now that the table is a child of any consuming component I am not sure how to dynamically add this click event. Here is an essentially what I am trying to achieve:
HTML:
<tr class="someClass" <!-- want click event here -->>
<td *ngFor="let column of row;"><div [innerHtml]="column"></div></td>
</tr>
This is the tables typescript file, where all the data is coming in on the visibleData object:
export class GenericTableComponent implements OnInit {
@Input() visibleData;
constructor() { }
ngOnInit() {
}
}
I implement the generic table in my parent HTML here
Parent HTML:
<oma-generic-table [visibleData]="visibleData"></oma-generic-table>
And here is a function in the parent which prepares the data. I have attempted to store the click event in a string and pass it but everything I've tried so far has failed (data binding with {{}}, square brackets, etc..).
transformData(visibleData) {
const ret: any = {};
ret.headings = visibleData.headings;
ret.action = '(click)="rowClicked([row.id])"';
ret.checkbox = this.checkBox; //add if the table needs checkboxes
ret.content = [];
for (let i = 0; i < visibleData.content.length; i++) {
ret.content.push(_.values(_.omit(visibleData.content[i], 'id')));
}
return ret;
}
However, even when hard coded into the child, the click event doesn't recognize the function in the parent and I get the following error:
EXCEPTION: Error in ./GenericTableComponent class GenericTableComponent - inline template:35:4 caused by: self.parentView.context.rowClicked is not a function
ORIGINAL EXCEPTION: self.parentView.context.rowClicked is not a function
I'm not sure if this is something simple or not. I'm new to Angular 2 so I apologize if this question is simplistic. Thanks in advance for any help.
Upvotes: 4
Views: 10747
Reputation: 6726
Your generic table can emit custom events to which parent component can subscribe:
@Component({
selector: 'oma-generic-table',
template: `
<table>
<tr *ngFor="let row of visibleData" class="someClass" (click)="selectRow(row)">
<td *ngFor="let column of row;"><div [innerHtml]="column"></div></td>
</tr>
</table>
`
})
export class OmaGenericTable {
@Input() visibleData: VisibleDataRow[];
@Output() select = new EventEmitter<VisibleDataRow>();
selectRow(row: VisibleDataRow) {
this.select.emit(row);
}
}
Then in your parent component:
// in template
<oma-generic-table
[visibleData]="visibleData"
(select)="tableRowSelected($event)"
></oma-generic-table>
// in component
tableRowSelected(r: VisibleDataRow) {
console.log(`Selected row ${r}`);
}
Upvotes: 11
Reputation: 679
Using this in HTML
<tr *ngIf="!isClickable" class="someClass">
<tr *ngIf="isClickable" class="someClass" #click>
<td *ngFor="let column of row;"><div [innerHtml]="column"></div></td>
</tr>
this in typescript
export class GenericTableComponent implements OnInit {
@Input() visibleData;
@ViewChild('click') protected _click:ElementRef;
constructor(enderer: Renderer) {
renderer.listen(this._click.nativeElement, 'click', (event) => {
// Do something with 'event'
})
}
}
Hope that help you
Upvotes: 0
Reputation: 171
Angular2 as far as I know will not bind to a "(click)" event that way. It may look ugly, but I would add the NgIf directive to the table on the row that the click event should act upon, and inversely apply the logic to another row that should not be affected by a click event. Ex:
<tr *ngIf="!isClickable" class="someClass">
<tr *ngIf="isClickable" class="someClass" (click)="rowClicked()>
<td *ngFor="let column of row;"><div [innerHtml]="column"></div></td>
</tr>
Then you can pass the isClickable variable as an input into your table from anywhere that you instantiate the table component, and act upon it.
Upvotes: 0