0

I have created a table, and I am able to generated a new row to the table on calling of addRow() function. generated button in the row is not able to call the myFunc(). how can I achieve that.

addRow(){
  let table = document.getElementById("tableData");
  let rowcount = table.rows.length;
  let row = table.insertRow(rowcount);
  row.insertCell(0).innerHTML= rowcount;
  row.insertCell(1).innerHTML= 'some fake data';
  row.insertCell(2).innerHTML= '<button (click)="myFunc()">click</button>';
  }

  myFunc(){
    alert()
  }
<table id="tableData" border="1" >
  <tr>
    <th>S.No.</th>
    <th>Name</th>
    <th>Operation</th>
  </tr>
</table>
Mukul Sharma
  • 176
  • 2
  • 5
  • 19
  • 3
    Is there a reason you're generating that html? You could do the same functionality via `ngIf Else`. The reason it's not executing is because when your TS is compiled to JavaScript it hasn't made the link to that function – Wesley Coetzee Sep 06 '17 at 07:53
  • 1
    you cannot add events to dynamically created html – Rahul Singh Sep 06 '17 at 07:54

3 Answers3

2

It seems that you don't understand the core principles of angular, don't manipulate the DOM directly when you don't have to. You should store your rows in an array and then loop trough it inside your template.

If you want to add a row, just add a new element to the array and angular will do the rest.

Components template:

<table>
  <tr>
    <th>S.No.</th>
    <th>Name</th>
    <th>Operation</th>
  </tr>
  <tr *ngFor="let row of myRows; let i = index">
    <td>{{ i + 1 }}</td>
    <td>{{ row.data }}</td>
    <td>
      <button (click)="myFunc()">click</button>
    </td>
  </tr>
</table>

And in your component:

public myData: { data: string }[] = [];

public addRow() {
  this.myData = this.myData.concat({
    data: 'some fake data'
  });
}

I strongly recommend that you should read the Fundamentals section of the docs.

cyr_x
  • 13,987
  • 2
  • 32
  • 46
0

The only way to make (click) or similar Angular specific stuff work for dynamically added HTML is to compile a component at runtime.

You can still do something like

constructor(private elRef:ElementRef) {}

addRow() {
  let table = document.getElementById("tableData");
  let rowcount = table.rows.length;
  let row = table.insertRow(rowcount);
  row.insertCell(0).innerHTML= rowcount;
  row.insertCell(1).innerHTML= 'some fake data';
  row.insertCell(2).innerHTML= '<button (click)="myFunc()">click</button>';

  this.elRef.nativeElement.querySelector('button').addEventHandler('click', this.clickHandler.bind(this));
}
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 4
    But please don't do this. :( Learn how to use Angular's native directives. If this is how you're going to build your app, then you shouldn't use Angular at all: it's actually just slowing you down (both you and the app). – Lazar Ljubenović Sep 06 '17 at 07:59
  • Even if (and i don't know a reason why) you want to do it like this, use the Renderer (Renderer2) to bind the click event! And `addEventHandler` doesn't exists. – cyr_x Sep 06 '17 at 08:01
  • I don't know what the current stance is from the Angular team. In the 2.0.0 pre-release phase they strongly suggested using `Renderer`, then there was a time where it was mentioned several times that it's not a strong suggestions, only if you consider using Server Side Rendering or WebWorker. Then I didn't hear or see anything about this topice, but also didn't have that much time to follow that closely. – Günter Zöchbauer Sep 06 '17 at 08:03
  • I am geeting error when I am implementing this `Cannot read property 'bind' of undefined` – Mukul Sharma Sep 06 '17 at 11:39
0

using render2 angular way to do it.

@ViewChild('myButton') myButton;
  let simple = this.renderer.listen(this.myButton.nativeElement, 'click', (evt) => {

                console.log('Clicking the button', evt);
                this.myFunc() //your func

            });

refer LINK for more infirmation.

k11k2
  • 2,036
  • 2
  • 22
  • 36