代码之家  ›  专栏  ›  技术社区  ›  Billy G

“角度材质”对话框:如何在父零部件中更改注入的数据时更新这些数据?

  •  30
  • Billy G  · 技术社区  · 6 年前

    向材质对话框中注入数据效果很好,但如果父/打开程序组件中的数据发生更改(例如来自(WAMP)订阅),如何自动更新这些数据?

    [更新]
    我制作了一个最低版本来尝试这种行为: https://stackblitz.com/edit/angular-njh44v?embed=1&file=src/app/app.component.ts
    打开右下方的控制台,单击带有数字的灰色框。您可以看到,该对话框获取当前编号,之后不再更新。
    [/更新]

    [更新2]
    基于Jusmpty的第二个想法,这种方法可以一目了然地工作(即使在数据到达后第一次显示/更新对话框): https://stackblitz.com/edit/angular-thd34f?embed=1&file=src/app/app.component.ts
    [/更新]

    具体案例如下:

    • 有一个 地区 订阅WAMP服务并获取所有 数据 对于包括 零件 。这将吸引所有 零件 带有*ngFor。
      文件 地区组成部分ts
    • 每个 部分 有自己的组件显示 数据 .如果 数据 在订阅更改中,对于每个/所有,视图都会正确自动更新 零件
      文件 部分组成部分ts 部分组成部分html
    • 在每个 部分 单击打开 对话 显示更多数据的位置。
      文件 “零件详细信息”对话框。组成部分ts “零件详细信息”对话框。组成部分html

    在最后一个操作/步骤中,会出现这样的问题:当前数据正在显示(注入),但如果订阅数据中的某些内容发生更改,则不会再更新。

    地区组成部分ts

    @Component({
      selector: 'app-area',
      template: '<app-part *ngFor="let part of plan" [partData]="part"></app-part>'
    })
    export class AreaComponent {
    
      plan = [];
    
      planasync$ = this.wampService
        .topic('sendplan')
        .subscribe(
          res => {
            let tm = new TableMap();
            this.plan = tm.tableToMap(res.argskw).filter((m) => m.area === 1);
          },
          err => console.log("res err", err),
          () => console.log("res complete"));
    
      constructor(private wampService: WampService) { }
    }
    

    部分组成部分ts

    import { PartDetailsDialogComponent } from './part-details-dialog/part-details-dialog.component';
    
    @Component({
      selector: 'app-part-details',
      templateUrl: './part.component.html'
    })
    export class PartComponent {
      @Input() partData: any;
    
      constructor(public dialog: MatDialog) {}
    
      openDetailsDialog(): void {
        let dialogRef = this.dialog.open(PartDetailsDialogComponent, {
          width: '650px',
          height: '400px',
          data: {
            partData: this.partData
          }
        });
      }
    }
    

    部分组成部分html

    <mat-card (click)="openDetailsDialog()">
      <mat-card-title>Nr: {{ partData.partNr }}</mat-card-title>
      <mat-card-content>
          <div>Current speed: {{ partData.speed }}</div>
      </mat-card-content>
    </mat-card>
    

    “零件详细信息”对话框。组成部分ts

    @Component({
      selector: 'app-part-details-dialog',
      templateUrl: './part-details-dialog.component.html'
    })
    export class PartDetailsDialogComponent {
    
      constructor(public dialogRef: MatDialogRef<PartDetailsDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: any) { }
    
      onNoClick(): void {
        this.dialogRef.close();
      }
    }
    

    “零件详细信息”对话框。组成部分html

    <h1 mat-dialog-title>Part Details for Nr. {{ data.partData.partNr }}</h1>
    <div mat-dialog-content>
      <div>Current speed details: {{ data.partData.speed }}</div>
    </div>
    <div mat-dialog-actions>
      <button mat-button (click)="onNoClick()">Cancel</button>
      <button mat-button [mat-dialog-close]="data.animal" cdkFocusInitial>Ok</button>
    </div>
    
    3 回复  |  直到 6 年前
        1
  •  59
  •   peng37    4 年前

    你可以改变 data 组件实例的,如下所示:

    this.dialogRef.componentInstance.data = {numbers: value};
    

    示例如下: https://stackblitz.com/edit/angular-dialog-update

        2
  •  2
  •   Jusmpty    6 年前

    目前我有两种想法,我都不喜欢,但是嘿。。。

    这两种方法都涉及通过数据向对话框发送一个可观察的对象。

    1. 您可以将零件的可观察值传递给零件组件,然后将数据中的可观察值传递给对话框。然后,对话框可以订阅observable并以这种方式获得更新。

    区域组件

    @Component({
      selector: 'app-area',
      template: '<app-part *ngFor="let part of planAsync$ | async; i as index" [partData]="part" [part$]="part$(index)"></app-part>'
    })
    export class AreaComponent {
    
      plan = [];
    
      constructor(private wampService: WampService) {
      }
    
      part$(index) {
        return this.planAsync$
          .map(plan => plan[index]);
      }
    
      get planAsync$() {
        return this.wampService
          .topic('sendplan')
          .map(res => {
            let tm = new TableMap();
            return tm.tableToMap(res.argskw).filter((m) => m.area === 1);
          });
      }
    }
    

    零件组件

    @Component({
      selector: 'app-part-details',
      templateUrl: './part.component.html'
    })
    export class PartComponent {
      @Input() partData: any;
      @Input() part$
    
      constructor(public dialog: MatDialog) {}
    
      openDetailsDialog(): void {
        let dialogRef = this.dialog.open(PartDetailsDialogComponent, {
          width: '650px',
          height: '400px',
          data: {
            partData: this.partData,
            part$: this.part$
          }
        });
      }
    }
    

    当然,接下来的问题是,如果您可以直接访问数据,那么传递partData有多有用。

    1. 另一种方法要求您只修改零件组件,但您必须创建一个主题,将更改提供给组件接收的零件。我真的不喜欢制作主题,尤其是如果数据最初来自一个可观察的对象,但不管怎样:

    零件组件

    @Component({
      selector: 'app-part-details',
      templateUrl: './part.component.html'
    })
    export class PartComponent, OnChanges {
      @Input() partData: any;
    
      private Subject part$ = new Subject();
    
      constructor(public dialog: MatDialog) {}
    
      ngOnChanges(changes){
        this.part$.next(changes['partData']);    
      }
    
      openDetailsDialog(): void {
        let dialogRef = this.dialog.open(PartDetailsDialogComponent, {
          width: '650px',
          height: '400px',
          data: {
            partData: this.partData,
            part$: this.part$
          }
        });
      }
    }
    

    最后,要访问数据,可以将html更改为

    对话框HTML

    <div *ngIf="(data.part$ | async) as part">
      <h1 mat-dialog-title>Part Details for Nr. {{ part.partNr }}</h1>
      <div mat-dialog-content>
        <div>Current speed details: {{ part.speed }}</div>
      </div>
      <div mat-dialog-actions>
        <button mat-button (click)="onNoClick()">Cancel</button>
        <button mat-button [mat-dialog-close]="data.animal" cdkFocusInitial>Ok</button>
      </div>
    </div>
    

    或者您可以订阅对话框组件中的observable,并从中提供数据

        3
  •  1
  •   Ramasubramanian    3 年前

    一个组件承载一个对话框。 如果组件数据已更改,则对话框数据也应更改。 为此,彭辉的第一个答案是可行的。

    如果该对话框必须根据数据更改执行某些操作,则不会有(事件)触发器通知对话框数据已更改。

    对此,解决方案是(也适用于此问题):

    步骤1:声明类变量dialogRef:MatDialogRef

    步骤2:在对话框组件板条箱中使用方法xMethod()

    步骤3:保留分配给此的对话框引用。dialogRef

    步骤4:每当托管组件想要更改对话框数据时,请在组件中使用以下行:

      if (this.dialogRef  && this.dialogRef.componentInstance) {
           this.dialogRef.componentInstance.xMethod( data);
      }
    

    步骤5:调用对话框中的check xMethod(),并从组件中写入要对数据更改事件执行的任何操作。

    请检查此工作代码:

    https://stackblitz.com/edit/angular-arvuho?embed=1&file=src/app/app.component.ts