Angular 4动态添加按钮点击事件

4
这是一个显示在循环中的按钮的代码。
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!");
}

这是动态数据渲染后页面的截图。 enter image description here

2
为什么要在for循环中创建一个表格?你可以在组件的模板中使用*ngFor属性来让Angular渲染表格。 - unkreativ
@PranayRana 我想在按钮上动态添加点击事件。 - Tarun Kumar
1
嗨,请告诉我你的数据结构,但我建议你像我一样使用ngFor和ngIf。 - Pranay Rana
@PranayRana 目前还没有任何事件起作用,且在消毒后未显示按钮,仅显示按钮文本。 - Tarun Kumar
你的问题在于你试图与Angular框架对抗。如果你正在以代码形式编写模板,那么你几乎总是在做一些错误的事情,并且不符合Angular方式。建议你使用ngFor是正确的。 - bryan60
显示剩余3条评论
4个回答

4

详细阅读: 使用-ngIf、*ngFor和ngSwitch实现动态Html结构

您可以尝试,下面的模板方式工作良好,几乎没有改变,以下只花了20分钟

App.Component.html --- 模板文件

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

没有模板动态方式

我花了5个小时才写出这段代码,但之后它可以正常工作,你需要使用 DomSanitizer 来绕过安全性检查,因为你想要在模板文件中放置输入元素。

//typings.d.ts
interface Window { my: any; }

上述代码扩展了您的window对象。

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 文件 - 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
  }
}

@TarunMishra - 试试这样 <input type="button" (click)="test()" value="点击"> - Pranay Rana
按钮单击应该在@PranayRana的代码中起作用。对于<a>标签,请尝试删除href="#"。 - raju
@raju - 是的,它应该可以工作,但他的问题是清理,Angular不允许您从ts文件中发出HTML标记,因此您需要绕过并允许其正确呈现...请查看我的更新答案...如果您喜欢,请点赞答案。 - Pranay Rana
@PranayRana 但是使用清理技术,删除按钮元素并仅打印按钮的文本。 - Tarun Kumar
这是在模板中实现极其简单的事情,却需要大量的工作量。 - bryan60

1
我将按照 Angular 的方式发布应该如何完成此操作的内容。在代码中编写 HTML 几乎总是意味着你正在做一些错误的事情。这是模板逻辑,应该在模板中完成,例如:
<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>

这是实现目标的Angular方式,全部在模板中完成,使用嵌套的ng for循环,然后ngSwitch是此用例的适当指令,因为您有2个选项和一个默认选项。现在您不需要与框架对抗或使用任何hack,如将函数绑定到窗口。Angular将使用此方法适当地绑定函数。您还具有显示驱动模型的明显优势,因此您只需要更新模型,显示就会相应地做出反应,因此您永远不需要担心显示和模型失去同步。
例如,如果您删除第5行,则需要在更新模型后手动重新绘制表格,如果添加新行或编辑第3行的单元格,则情况相同。使用模板,Angular以透明且可靠的方式管理所有这些内容。

-1

这是我用的代码,可能对你们也有帮助。

<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> 

我已经提供了带有ngSwitch语句的相同代码...我认为你至少应该检查一下给你的答案...我从一开始就告诉你要使用*ngFor,但你从未尝试过... - Pranay Rana
但是你至少应该给那些帮助你解决问题的人点赞...你是根据他们给你的答案找到了解决方案...所以那些给你答案的人,你至少要感谢他们...点赞或接受他们的答案,但你是基于答案找到了解决方案,却没有至少欣赏为你解决问题的人。 - Pranay Rana
你几乎在 SO 上问了5到10个问题,但从未接受任何答案... 你应该知道如何接受或点赞答案。 - Pranay Rana
看啊,伙计,我没有使用你的代码或其他人的代码,所以我不认为我需要投票给任何人。 - Tarun Kumar
你提出了问题,我和其他人提供了答案...那是正确的...我根据你的输入给出了两种方法,这两种方法都是正确的...然后你应该至少说它正在工作...我知道你对第二种方法有问题,但第一种方法是有效的... - Pranay Rana
显示剩余2条评论

-3
如上所述,您可以在组件的 HTML 文件中的表格行中使用 *ngFor。然后像平常一样处理按钮标签的单击事件。
<td> <button (click)="clickEvent()"> Click </button> </td>

然后在你的组件.ts文件中定义点击事件

clickEvent(){console.log("click event triggered")}

不想在组件中编写 HTML,请查看上面的代码。 - Tarun Kumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接