Reputation: 148
Here is the code of button displayed from loop.
for( let k=0; k<this.newTmpArr.length; k++ ){
myTable += "<tr>";
for( let key2 in this.newTmpArr[k] ){
if(this.newTmpArr[k][key2] == 'button' ){
myTable += `<td><button (click)="test()">Click</button></td>`;
break;
}
if(this.newTmpArr[k][key2] == 'link' ){
myTable += `<td><a href="#" (click)="test()">Click</a></td>`;
break;
} else {
myTable += "<td>" + this.newTmpArr[k][key2] + "</td>";
}
}
myTable += "</tr>";
}
test(){
alert("Working!");
}
Here is the screenshot of the page look like after dynamic data rendered.
Upvotes: 4
Views: 22156
Reputation: 176896
Read for detail : Dynamic Html Structure with - *ngIf, *ngFor & ngSwitch
you can try out , Template way below is working fine without much change, below took just 20 min
App.Component.html --- template file
<table>
<thead>
<tr>
<th>ID</th>
<th>Date</th>
<th>Ammount</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let ele of newTmpArr" >
<td>{{ele[0]}}</td>
<td>{{ele[1]}}</td>
<td>{{ele[2]}}</td>
<td>
<div ngSwitch="{{ele[3]}}">
<div *ngSwitchCase="'button'">
<input type="button" (click)="DoWork(1)" value="click"/>
</div>
<div *ngSwitchCase="'link'">
<a href="#" (click)="DoWork(1)" >click</a>
</div>
</div>
</td>
</tr>
</tbody>
</table>
App.Component.ts--typescript
export class AppComponent implements OnInit {
ngOnInit(): void {}
title = 'app';
DoWork()
{
//here you can do work ,
//this get called when you press "click" button in table
alert(this.title);
}
}
Without template dynamic way
It took me 5 hours to reach this code but fater that Following is working fine , you need to by pass security with the help of DomSanitizer
as you want to put input element from you template file.
//typings.d.ts
interface Window { my: any; }
above one extends your window object
app.Component.html
<table>
<thead>
<tr>
<th>ID</th>
<th>Date</th>
<th>Ammount</th>
<th>Action</th>
</tr>
</thead>
<tbody id="tid" [innerHTML]="bodytext"></tbody>
</table>
typescript file - app.Component.ts
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import {Component, NgZone, OnInit, OnDestroy} from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
title = 'app';
_myTable : string;
bodytext ;
newTmpArr = [
["567", "2017-04-17T14:22:48", "45000", "button"],
["567", "2017-04-17T14:22:48", "45000", "button"],
["567", "2017-04-17T14:22:48", "45000", "link"],
["567", "2017-04-17T14:22:48", "45000", "button"]
];
constructor(private http: Http,private _sanitizer:
DomSanitizer,private ngZone: NgZone) {
}
ngOnInit(): void {
//below code add dynamci table to your html
for( let k=0; k<this.newTmpArr.length; k++ ){
this._myTable += "<tr>";
for( let key2 in this.newTmpArr[k] ){
if(this.newTmpArr[k][key2] == 'button' ){
//below is table click button calls angular function,
//here 1 is passed as arugment you can pass
//any other value you want
//or if you dont want to pass than just do
// onclick="my.namespace.publicFunc();"
// and remove parameter from typscript function also
this._myTable += `<td><input type="button"
onclick="my.namespace.publicFunc(1);"
value="Click me" /></td>`;
break;
}
if(this.newTmpArr[k][key2] == 'link' ){
this._myTable += `<td><a href="#"
onclick="my.namespace.publicFunc(1);
return false;">Click</a>
</td>`;
break;
} else {
this._myTable += "<td>" +
this.newTmpArr[k][key2] + "</td>";
}
}
this._myTable += "</tr>";
}
this.bodytext =
this._sanitizer.bypassSecurityTrustHtml(this._myTable);
//code to add dynamic html ends here
//below script helps to expose anglar function to javascript
window.my = window.my || {};
window.my.namespace = window.my.namespace || {};
//below line bind typescript function to window object publicFunc
window.my.namespace.publicFunc =
this.OnTableButtonClick.bind(this);
//code to expose typscipt function ends here
}
//this function get called when Table click button ge clicked
public OnTableButtonClick(input:string):void{
this.ngZone.run(() => this.DoWork(input));
}
DoWork(input:string)
{
//here you can do work ,
//this get called when you press "click" button in table
alert(this.title + input);
//this will display app1 in output
}
}
Upvotes: 4
Reputation: 148
here is the code work for me. it may helpful for you guys too.
<tr *ngFor="let item of newTmpArr">
<td *ngFor="let i of item">
<span *ngIf="i.value; then dynamicVal; else elseblock"></span>
<ng-template #dynamicVal>
<span *ngIf="i.type == 'button'">
<button (click)="clickMe(item)">Click</button>
</span>
<span *ngIf="i.type == 'link'">
<a [href]="i.link">{{i.value}}</a>
</span>
</ng-template>
<ng-template #elseblock>{{i}}</ng-template>
</td>
</tr>
Upvotes: -1
Reputation: 29325
I'm going to go ahead and post the way I feel this should be done, in the angular way. Writing html in code almost always means you're doing something wrong. This is template logic that should be done IN TEMPLATE, like this:
<tr *ngFor="let row of newTmpArr">
<td *ngFor="let cell of row">
<ng-container [ngSwitch]="cell">
<button *ngSwitchCase="'button'" (click)="test()">Click</button>
<a *ngSwitchCase="'link'" href="#" (click)="test()">Click</a>
<ng-container *ngSwitchDefault>{{ cell }}</ng-container>
</ng-container>
</td>
</tr>
This is the angular way of achieving your goal, all done in template, using nested ng for loops and then an ngSwitch is the appropriate directive for this use case since you have 2 options and a default. Now you do not need to fight the framework or use any hacks like binding functions to the window. Angular will bind functions appropriately using this method. You also have the distinct advantage of your display being model driven, so you only need to ever update your model and the display will react accordingly, so you never need to worry about display and model falling out of sync.
For example if you were to remove row 5, you would need to manually redraw your table after updating your model, same if you added a new row, or if you edit cell 2 of row 3. Using template, angular manages all of this in a transparent and reliable manner.
Upvotes: 1
Reputation: 5
As said above you can use the *ngFor in your table row in your component.html file. Then in the button tag handle the click event as you would normally do.
<td> <button (click)="clickEvent()"> Click </button> </td>
Then in your component.ts file define the on click event
clickEvent(){console.log("click event triggered")}
Upvotes: -3