Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 passing a click event to a reusable generic component

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.

like image 634
Chris Sharp Avatar asked Dec 19 '22 09:12

Chris Sharp


1 Answers

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}`);
}
like image 109
Vilmantas Baranauskas Avatar answered Dec 30 '22 17:12

Vilmantas Baranauskas