4

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.

enter image description here

8
  • 2
    Why do you create a table in a for loop??? You can ask angular to render the table using *ngFor attribute in your component#s template Commented Dec 6, 2017 at 7:39
  • @PranayRana I want to add click event dynamically on button Commented Dec 6, 2017 at 7:40
  • 1
    hi, let me know structure of you data , but i suggest you do like as I did make use of *ngFor with *ngIf Commented Dec 6, 2017 at 7:45
  • @PranayRana no event working yet and not button showing after Sanitization, showing only text of button. Commented Dec 6, 2017 at 8:16
  • @PranayRana here is the jsfiddle link: jsfiddle.net/tarunmishra592/a32qj7ch/1 Commented Dec 6, 2017 at 9:47

4 Answers 4

4

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
  }
}
Sign up to request clarification or add additional context in comments.

5 Comments

@TarunMishra - try like this <input type="button" (click)="test()" value="Click">
Button click should work in @PranayRana code. For <a> tag try to remove href="#"
@raju - yes it should work but for him problem is Sanitization , angular not allow you to emit html tag from ts file , so you need to go around and allow it to render properly...have look to may updated answer ...do upvote answer if you like it
@PranayRana but using Sanitization remove button element print only text of button
this is a huge level of work around for something extremely simple to accomplish in template
1

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.

Comments

-1

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> 

7 Comments

i provided you same code with ngSwitch statement ...i think you should atleast check answers ...given to you ...i told you from begining make use of *ngFor but you never tried it ..
but you should atlest upvote to people who helped you to reach your solution ... you reached to solution based on answer given to you...so those who gives you answer atlest you thank them ..upvote or accept there answer but you came with solution based on answer and not atlest appericieated person worked for you solution....
you almost asked 5 to 10 question on so but never accept any answer ...you should should know how to accept/uvote anser
See buddy I didn't use ur code or other person of code so I don't think I have to vote anyone.
you asked question and I and other persons provided answer ...that is correct ..I given you two way based on your input ,and both are correct way based on your input .........than you should altest say its working ...i know you have problem with second approch but first one is working ...
|
-3

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")}

1 Comment

Don't want to write html in component. please have a look code up.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.