在 Angular 2 个子组件之间使用 @input 和 @output

Using @input and @output between Angular 2 child components

我有一个 ng-table,它是我主页的子组件。单击一行时,它会使用 EventEmitter 通过 onCellClick 发送该行中的信息。我正在尝试将此信息发送到另一个子组件。这恰好是一个按钮,它是 Bootstrap 4 模式的子级,当单击主页上的按钮时弹出。只是在接收和处理该信息时遇到问题。

HTML 子组件 table:

<ng-table [config]="config"
      (tableChanged)="onChangeTable(config)"
      (cellClicked)="onCellClick($event)"
      [rows]="rows" [columns]="columns">
</ng-table>

HTML 对于子组件(这出现在主页的 HTML):

<app-datatable (row)="received($event)"></app-datatable>

用于获取和发送行数据的 Typescript(this.row 是 EvenEmitter。data.row 是被点击的实际行):

@Output() row: EventEmitter<any> = new EventEmitter<any>();
public onCellClick(data: any): any {
  let d = data.row.tDataPoint;
  let i = data.row.tICCP;
  let s = data.row.tStartDate;
  let e = data.row.tEndDate;
  let toSend:DataTable = new DataTable(d, i, s, e);
  this.row.emit(toSend);
}

HTML 对于作为 Bootstrap 4 模态的子组件的按钮:

<button type="submit" class="btn" data-dismiss="modal" (click)="onClick($event)">Delete</button>

按钮子组件的打字稿:

selector: 'deletebutton'
@Input() receivedRow:DataTable;
onClick(message:DataTable){
  this.sender.emit('This is from On Click Deletebutton');
  console.log("On Click Deletebutton");
  console.log(this.receivedRow);
  for (let entry in DPS){
    if (DPS[entry].tDataPoint===message.tDataPoint){
    DPS.splice(parseInt(entry),1);
    }
  }
}
按钮子组件的

HTML(这出现在模态的 HTML 中)。这实际上应该从单击的行接收数据作为输入。

<deletebutton [receivedRow]='row'></deletebutton>

现在在我的 onClick 方法中说 receivedRow 未定义。我觉得缺少的是 [receivedRow]='row' 我的 deletebutton HTML 和 HTML 中该子组件的 onClick 函数调用之间的协调。总的来说,我只想单击一行,单击按钮打开删除 Boostrap 模态,然后删除正确的行我单击模态内的 Delete 按钮。如果有什么不清楚或需要更多代码,请告诉我。

是否真的有一种方法可以像这样使用@Input 和@Output 在子组件之间进行通信?

使用angular2,你的数据流应该是:
- 向下传递数据
- 最多发送事件

所以如果你真的想走这条路,你应该有这样的东西:

我认为还有更好的方法:
对于您的应用程序和您的用户,最好在每一行都有一个删除按钮。这样,它可以避免用户混淆单击一行然后单击删除按钮,并且在您的代码中您将能够执行类似的操作:

src/app.html :

<table class="table">
  <tr *ngFor="let row of tableData">
    <td *ngFor="let column of row.columns">
      {{ column.name }}
    </td>

    <td (click)="deleteRow(row)"><button>X</button></td>
  </tr>
</table>

<button (click)="addRow()">Add a row</button>

src/app.ts (此处仅缩减为 class) :

@Component({
  selector: 'app',
  templateUrl: `./src/app.html`,
})
export class App {
  private tableData;
  private cptRow = 1;

  constructor() {
    this.tableData = [
      {
        idRow: `idR${this.cptRow++}`,
        columns: [
          {idColumn: 'idR1C1', name: 'Column 1-1'},
          {idColumn: 'idR1C2', name: 'Column 1-2'},
          {idColumn: 'idR1C3', name: 'Column 1-3'}
        ]
      },
      {
        idRow: `idR${this.cptRow++}`,
        columns: [
          {idColumn: 'idR2C1', name: 'Column 2-1'},
          {idColumn: 'idR2C2', name: 'Column 2-2'},
          {idColumn: 'idR2C3', name: 'Column 2-3'}
        ]
      },
      {
        idRow: `idR${this.cptRow++}`,
        columns: [
          {idColumn: 'idR3C1', name: 'Column 3-1'},
          {idColumn: 'idR3C2', name: 'Column 3-2'},
          {idColumn: 'idR3C3', name: 'Column 3-3'}
        ]
      }
    ];
  }

  deleteRow(row) {
    // we can do this by reference ...
    // this.tableData = this.tableData.filter(r => r !== row);

    // or by ID
    this.tableData = this.tableData.filter(r => r.idRow !== row.idRow);
  }

  addRow() {
    this.tableData.push({
      idRow: `idR${this.cptRow}`,
      columns: [
        {idColumn: `idR${this.cptRow}C1`, name: `Column ${this.cptRow}-1`},
        {idColumn: `idR${this.cptRow}C2`, name: `Column ${this.cptRow}-2`},
        {idColumn: `idR${this.cptRow}C3`, name: `Column ${this.cptRow}-3`}
      ]
    });

    this.cptRow++;
  }
}

这是一个可用的 Plunkr:http://plnkr.co/edit/hNhcdraoDNnI2C92TQvr?p=preview

现在,如果你真的想使用 input/output 属性,你应该寻找教程,因为这里的结构似乎有点混乱。我可以帮助你理解这一点(用 angular2 理解它很重要!)但也许你应该在 Gitter/Angular 上大声疾呼,而不是在这里详细说明 Angular2 流程 :)

一种解决方法是将删除按钮组件放置在 table 组件的 HTML 中,如下所示:

<ng-table [config]="config"
      (tableChanged)="onChangeTable(config)"
      (cellClicked)="onCellClick($event)"
      [rows]="rows" [columns]="columns">
</ng-table>
<deletebutton [receivedRow]='toSend'></deletebutton>

并且仍然像我一样在主页的 HTML 中保留 table 的标签:

<app-datatable (row)="received($event)"></app-datatable>

现在该行的数据被发送到删除按钮,因为它在技术上是主页子组件的一部分。

仍然无法像我在问题中所问的那样在子组件之间进行通信。但这是可行的。