如何使用EventEmitter将值从模态传递给父级?

时间:2019-07-05 14:04:15

标签: angular

我有一个组件,该组件当前以表的形式显示许多对象的属性。我要为此表创建的功能之一是能够选择特定行上的按钮并从表中删除该行。为此,该应用程序首先向用户显示一个模态,要求用户确认删除,一旦用户选择了该勾号,就应删除该行。

目前,我正在处理模式,直到实际删除行为止。我可以删除行,但是我需要一种方式让模式将应该删除的行的ID传递回父级,以便它可以调用deleteRow(id),这是我读过的一种可能的方式是通过使用EventEmitter

我已将EventEmitted编码到我的模式组件中,但是对于在哪里需要从父级访问事件感到困惑。在此处显示的示例中:https://angular.io/guide/component-interaction通过执行

访问eventemitter值
<app-voter *ngFor="let voter of voters"
      (voted)="onVoted($event)">
    </app-voter>

其中app-voter是孩子,voted是发出的值。但是,由于我使用的是模态,所以在父模板的任何地方都没有模态模板的实例,因此无法执行此操作。因此,我需要一些其他方式来接收值。我还能做什么?

SessionViewerTemplate

<div class="session-table-container">
  <div class="row justify-content-center">
    <table class="session-table" mat-table [dataSource]="dataSource">

      <ng-container matColumnDef="id">
        <mat-header-cell *matHeaderCellDef>Id</mat-header-cell>
        <mat-cell *matCellDef="let element">{{element.sessionId}}</mat-cell>
      </ng-container>

      <ng-container matColumnDef="delete">
        <mat-header-cell *matHeaderCellDef>Control</mat-header-cell>
        <mat-cell *matCellDef="let row">
          <button mat-icon-button (click)="showDeleteModal(row)"><mat-icon><fa name="trash" size="lg"></fa></mat-icon></button>
        </mat-cell>
      </ng-container>

      <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
      <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
    </table>
  </div>
</div>

SessionViewerComponent

export class SessionViewerComponent implements OnInit {

  @Input() sessions: SessionDetail[];

  displayedColumns: string[] = ['id', 'name', 'date', 'link', 'delete']
  dataSource: MatTableDataSource<SessionDetail>;

  constructor(private dialog: MatDialog) { }

  ngOnInit() {
    console.log(this.sessions);
    this.dataSource = new MatTableDataSource<SessionDetail>(this.sessions);
  }

  showDeleteModal(row: any): void{
    let deleteModalRef = this.dialog.open(SessionDeleteModalComponent, {
      data: {
        id: row.sessionId,
        name: row.sessionName,
      }
    });
  }

  deleteRow(index: number): void{  //<-- This is the function I need to pass the emitted ID to

    this.sessions.splice(index,1);
    console.log(this.sessions);
    this.dataSource = new MatTableDataSource<SessionDetail>(this.dataSource.data);
  }

}

SessionDeleteModalTemplate

<div class="container">
  <div class="row">
    <p>Are you sure you wish to delete {{data.name}}?</p>
  </div>
  <div class="row">
    <div class="col delete-modal-center">
      <button mat-icon-button (click)="deleteSession()"><mat-icon><fa name="check" size="lg"></fa></mat-icon></button>
    </div>
    <div class="col delete-modal-center">
      <button mat-icon-button (click)="closeDialog()"><mat-icon><fa name="times" size="lg"></fa></mat-icon></button>
    </div>
  </div>
</div>

SessionDeleteModalComponent

export class SessionDeleteModalComponent implements OnInit {

  @Output() deleteIndex = new EventEmitter<number>(); //<-- Here is where I am emitting the value

  constructor(public dialogRef: MatDialogRef<SessionDeleteModalComponent>,
              @Inject(MAT_DIALOG_DATA) public data: any) { }

  ngOnInit() {
  }

  deleteSession(): void{
    this.deleteIndex.emit(this.data.sessionId);
  }

  closeDialog(): void {
    this.dialogRef.close();
  }

}

2 个答案:

答案 0 :(得分:0)

使用EventEmitter是使代码可重用的好方法,因为您的组件不需要了解有关父组件的任何信息,而父组件只需要绑定到该事件即可。

这里的问题是,您正在动态地创建模态组件,因此该解决方案可能并不理想,至少对我而言是这样。

但是您可以在关闭模态/输入删除按钮时返回数据

所以在您的代码中,我会做类似的事情

SessionDeleteModalComponent:

  deleteSession(): void{
   // you don't need this anymore.
   // this.deleteIndex.emit(this.data.sessionId);
     this.dialogRef.close(this.data.sessionId);
  }

SessionViewerComponent:

 showDeleteModal(row: any): void{
    let deleteModalRef = this.dialog.open(SessionDeleteModalComponent, {
      data: {
        id: row.sessionId,
        name: row.sessionName,
      }
    });
   // NEW CODE HERE
   deleteModalRef.afterClosed().subscribe( id => {
       this.deleteRow(id);
   });

  }

让我知道它是否有效,因为未经测试:D 希望这可以帮助。

答案 1 :(得分:0)

您可以传递数据以关闭模态

  closeDialog(): void {
    const someData = {
        foo: "bar"
    }
    this.dialogRef.close(someData);
  }
showDeleteModal(row: any): void{
    let deleteModalRef = this.dialog.open(SessionDeleteModalComponent, {
      data: {
        id: row.sessionId,
        name: row.sessionName,
      }
    }).afterClosed().subscribe(result => {
        //do something with result
    });
  }

如果希望事件在打开模式时发生,则需要将服务注入到两者中。 :)