【问题标题】:Angular 2 passing a click event to a reusable generic componentAngular 2 将点击事件传递给可重用的通用组件
【发布时间】:2017-02-22 03:29:57
【问题描述】:

我有几个组件使用基本相同的表,因此我正在抽象出该表。我已经解决了大部分动态表填充需求,但还没有找到解决以下问题的方法。

在我的一个表格实例中,行需要是可点击的。在原始表中,我只是在行中添加了一个点击事件,并让它在我的打字稿文件中调用一个函数。

现在该表是任何消费组件的子代,我不确定如何动态添加此点击事件。这基本上是我想要实现的目标:

HTML:
<tr class="someClass" <!-- want click event here -->>
  <td *ngFor="let column of row;"><div [innerHtml]="column"></div></td>
</tr>

这是表格的打字稿文件,所有数据都来自 visibleData 对象:

export class GenericTableComponent implements OnInit {
    @Input() visibleData;
    constructor() { }

    ngOnInit() {
    }
}

我在这里在我的父 HTML 中实现通用表

Parent HTML:
<oma-generic-table [visibleData]="visibleData"></oma-generic-table>

这是父级中准备数据的函数。我试图将点击事件存储在一个字符串中并传递它,但到目前为止我尝试的一切都失败了(与 {{}} 的数据绑定、方括号等)。

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

但是,即使硬编码到子项中,点击事件也无法识别父项中的函数,并且我收到以下错误:

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

我不确定这是否简单。我是 Angular 2 的新手,所以如果这个问题过于简单,我深表歉意。提前感谢您的帮助。

【问题讨论】:

    标签: javascript html angular typescript event-handling


    【解决方案1】:

    您的通用表可以发出父组件可以订阅的自定义事件:

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

    然后在你的父组件中:

    // in template
    <oma-generic-table 
            [visibleData]="visibleData" 
            (select)="tableRowSelected($event)"
    ></oma-generic-table>
    
    // in component
    tableRowSelected(r: VisibleDataRow) {
        console.log(`Selected row ${r}`);
    }
    

    【讨论】:

    • 感谢您提供这个优雅的解决方案。我确实有几个问题。 1. 'VisibleDataRow' 在哪里声明?传入的对象是一个复杂的对象,其中包括表标题和行数组,以及一些其他属性。我不确定 VisibleDataRow 代表什么,或者我最初的解释是否不充分。抱歉,如果它具有误导性。 2. 为了使可点击功能成为可选功能,我正在考虑将'style="cursor:pointer"'字符串传递给任何希望使行可点击的父母。这是一种骇人听闻的方法吗?再次感谢!
    • 1.由于您没有在问题中指定任何类型的行,我只是使用 VisibleDataRow 来表示它。 “visibleData”是您可能拥有的任何类型对象的数组。 2. 您可以添加另一个输入参数 [selectable]="true" 来启用/禁用表格行选择。在您的 OmaGenericTableComponent 内部,您可以使用“@HostBinding('class.selectable') @Input() selectable: boolean;”基于此输入参数绑定必要的 css 类声明。
    【解决方案2】:

    据我所知,Angular2 不会以这种方式绑定到“(单击)”事件。它可能看起来很难看,但我会将 NgIf 指令添加到单击事件应作用的行上的表中,并将逻辑反向应用于不应受单击事件影响的另一行。例如:

    <tr *ngIf="!isClickable" class="someClass"> <tr *ngIf="isClickable" class="someClass" (click)="rowClicked()> <td *ngFor="let column of row;"><div [innerHtml]="column"></div></td> </tr>

    然后,您可以将 isClickable 变量作为输入从您实例化表格组件的任何位置传递到表格中,并对其进行操作。

    【讨论】:

      【解决方案3】:

      在 HTML 中使用它

      <tr *ngIf="!isClickable" class="someClass">
       <tr *ngIf="isClickable" class="someClass" #click>
        <td *ngFor="let column of row;"><div [innerHtml]="column"></div></td>
       </tr>
      

      打字稿中的这个

      export class GenericTableComponent implements OnInit {
          @Input() visibleData;
          @ViewChild('click') protected _click:ElementRef;
      
          constructor(enderer: Renderer) {
              renderer.listen(this._click.nativeElement, 'click', (event) => {
                  // Do something with 'event'
              })
          }
      }
      

      希望对你有帮助

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-01-03
        • 2017-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多