【问题标题】:Angular Material Table - Row Index is Inconsistent角材料表 - 行索引不一致
【发布时间】:2019-10-24 10:36:33
【问题描述】:

tl;博士; - 见下面我的回答;解决方案是提供trackBy功能

我有一个使用 mat-table 的简单时间表应用程序,用户可以在其中添加一周中每一天的工作时间。

添加和删除以特定顺序添加的行不起作用。

重现问题的步骤:

添加一个新行,将 Sunday 设置为 1 添加另一行并将星期日设置为 2 删除第一行 - 现在会有一行 Sunday=2 符合预期 现在添加另一个新行。 预期行为 - 添加新行,第一行周日值仍为 2。 实际行为 - 添加了新行,但第一行已重置为 0,就像我得到了 2 个新行。

我知道有很多推荐的方法来设置表数据源——我都试过了,但没什么区别。每次添加/删除时,下面显示的版本都会重新实例化数据源,但我也尝试设置 datasource.data 属性,但没有区别。底层数组总是包含预期值,只是在上面概述的场景中,表似乎没有正确绑定。

我已经从这个应用程序中剥离了核心功能,并对这个问题做了一个简单的演示,并上传到这里:Github。这是 Angular 8 和 angular-material 8。同样的事情发生在 Angular 7 上。

这是标记

    <div class='timesheets'>


  <div>Timesheets</div>
  <form #formControl="ngForm" autocomplete="off">
  <mat-table [dataSource]="timesheetEntryDataSource" #timesheetTable matSort>  

          <ng-container matColumnDef="actions">
              <mat-header-cell *matHeaderCellDef class='actions'> 
                <button mat-icon-button color="primary" (click)="add()" [disabled]="!!attendance?.approvalDate">
                    <mat-icon aria-label="Add">add</mat-icon>
            </button>                  
              </mat-header-cell>
              <mat-cell *matCellDef="let entry"  class='actions'>
                  <button mat-icon-button color="primary" (click)="remove(entry)" >
                      <mat-icon aria-label="Delete">delete</mat-icon>
                  </button>
              </mat-cell>
              <mat-footer-cell *matFooterCellDef class='actions'></mat-footer-cell>  
          </ng-container>

          <ng-container matColumnDef="sunday">
              <mat-header-cell *matHeaderCellDef>Sunday</mat-header-cell>
              <mat-cell *matCellDef="let entry;let i = index;" class="hours">
                      <mat-form-field>
                          <input min=0  max=23.75 pattern="^(?!0\d)\d+(?:[.](?:25|5|75|0)0*)?$" required #today="ngModel" matInput [(ngModel)]="entry.sundayHours"  name="sunday{{i}}">
                      </mat-form-field>
                  </mat-cell>   
                  <mat-footer-cell *matFooterCellDef></mat-footer-cell>              
          </ng-container>
          <ng-container matColumnDef="monday">
              <mat-header-cell *matHeaderCellDef>Monday</mat-header-cell>
              <mat-cell *matCellDef="let entry;let i = index;" class="hours">

                  <mat-form-field>
                      <input min=0  max=23.75 pattern="^(?!0\d)\d+(?:[.](?:25|5|75|0)0*)?$" required #today="ngModel" matInput [(ngModel)]="entry.mondayHours"  name="monday{{i}}">
                  </mat-form-field>
                  </mat-cell>
                  <mat-footer-cell *matFooterCellDef></mat-footer-cell>  
          </ng-container>

          <ng-container matColumnDef="tuesday">
              <mat-header-cell *matHeaderCellDef>Tuesday</mat-header-cell>
              <mat-cell *matCellDef="let entry;let i = index;" class="hours">
                      <mat-form-field>
                          <input min=0  max=23.75 pattern="^(?!0\d)\d+(?:[.](?:25|5|75|0)0*)?$" required #today="ngModel" matInput [(ngModel)]="entry.tuesdayHours" name="tuesday{{i}}">
                      </mat-form-field>
                  </mat-cell>
                  <mat-footer-cell *matFooterCellDef></mat-footer-cell>  
          </ng-container>

          <ng-container matColumnDef="wednesday">
              <mat-header-cell *matHeaderCellDef>Wednesday</mat-header-cell>
              <mat-cell *matCellDef="let entry;let i = index;" class="hours">
                      <mat-form-field>
                          <input min=0  max=23.75 pattern="^(?!0\d)\d+(?:[.](?:25|5|75|0)0*)?$" required #today="ngModel" matInput [(ngModel)]="entry.wednesdayHours" name="wednesday{{i}}">
                      </mat-form-field>
                  </mat-cell>
                  <mat-footer-cell *matFooterCellDef></mat-footer-cell>  
          </ng-container>

          <ng-container matColumnDef="thursday">
              <mat-header-cell *matHeaderCellDef>Thursday</mat-header-cell>
              <mat-cell *matCellDef="let entry;let i = index;" class="hours">
                      <mat-form-field>
                          <input min=0  max=23.75 pattern="^(?!0\d)\d+(?:[.](?:25|5|75|0)0*)?$" required #today="ngModel" matInput [(ngModel)]="entry.thursdayHours" name="thursday{{i}}">
                      </mat-form-field>
                  </mat-cell>
                  <mat-footer-cell *matFooterCellDef></mat-footer-cell>  
          </ng-container>

          <ng-container matColumnDef="friday">
              <mat-header-cell *matHeaderCellDef>Friday</mat-header-cell>
              <mat-cell *matCellDef="let entry;let i = index;" class="hours">
                      <mat-form-field>
                          <input min=0  max=23.75 pattern="^(?!0\d)\d+(?:[.](?:25|5|75|0)0*)?$" required #today="ngModel" matInput [(ngModel)]="entry.fridayHours"  name="friday{{i}}">
                      </mat-form-field>
                  </mat-cell>
                  <mat-footer-cell *matFooterCellDef></mat-footer-cell>  
          </ng-container>

          <ng-container matColumnDef="saturday">
              <mat-header-cell *matHeaderCellDef>Saturday</mat-header-cell>
              <mat-cell *matCellDef="let entry;let i = index;" class="hours">
                      <mat-form-field>
                          <input min=0  max=23.75 pattern="^(?!0\d)\d+(?:[.](?:25|5|75|0)0*)?$" required #today="ngModel" matInput [(ngModel)]="entry.saturdayHours"  name="saturday{{i}}">
                      </mat-form-field>
              </mat-cell>
              <mat-footer-cell *matFooterCellDef></mat-footer-cell>   
          </ng-container>


          <mat-header-row *matHeaderRowDef="timesheetColumns"></mat-header-row>
          <mat-row *matRowDef="let row; columns: timesheetColumns;"></mat-row>
          <mat-footer-row *matFooterRowDef="timesheetColumns"></mat-footer-row>
      </mat-table>

      </form>
</div>

还有代码:

import { Component } from '@angular/core';

import { MatTableDataSource  } from '@angular/material';




export class TimesheetEntry {
  mondayHours:string = '0'
  tuesdayHours:string = '0'
  wednesdayHours:string = '0'
  thursdayHours:string = '0'
  fridayHours:string = '0'
  saturdayHours:string = '0'
  sundayHours:string = '0'
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  title = 'tabledemo';

  timesheetEntryDataSource: MatTableDataSource<TimesheetEntry>;
  timesheetColumns = ['actions', 'sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'  ];

  tmpTimesheet:TimesheetEntry[] = [];


  constructor( ) { }


  ngOnInit() {
    this.timesheetEntryDataSource = new MatTableDataSource<TimesheetEntry>([]);
  }



  add(){
    this.tmpTimesheet.push(new TimesheetEntry());
    this.timesheetEntryDataSource = new MatTableDataSource<TimesheetEntry>(this.tmpTimesheet.slice());

  }

  remove(exception: TimesheetEntry){
    this.tmpTimesheet.splice(this.tmpTimesheet.findIndex(e => e === exception),1);
    this.timesheetEntryDataSource = new MatTableDataSource<TimesheetEntry>(this.tmpTimesheet.slice());
  }

  typeComparatorFn(select, option) {
    return select && option ? select.code === option.code : select === option;
  }



}

【问题讨论】:

  • 更新 - 问题似乎是表单标签。删除它并且它可以工作 - 问题是,我需要表格。需要进一步调查。
  • 很难说什么,很多事情都可能出错。如果您可以创建一个 stackblitz,将很容易回答。我看到的一件事是错误的-您的按钮没有type 属性,因此默认情况下它们是submit,并且无论何时单击,都会提交表单。将button 类型添加到&lt;form&gt; - &lt;button mat-icon-button type="button" 中的那些
  • Stackblitz 在这里创建:angular-mbsl9r.stackblitz.io

标签: angular angular-material mat-table


【解决方案1】:

问题是使用索引来创建唯一的名称属性(在表单标签中使用 ngModel 时需要名称属性 - 我正在使用模板化表单)。

*matCellDef="let entry;let i = index;"

<input min=0  max=23.75 pattern="^(?!0\d)\d+(?:[.](?:25|5|75|0)0*)?$" required #today="ngModel" matInput [(ngModel)]="entry.sundayHours"  name="sunday{{i}}">

似乎在数据源中添加和删除项目并没有一致地更新更新索引,在我的场景中,我最终得到了两个具有相同索引的条目。

解决方案是指定documentation中指定的trackBy函数

就我而言,我将其添加到 .ts 文件中:

  trackByFn(index, item) {
return index;

}

在标记中:

<mat-table [dataSource]="tmpTimesheet" [trackBy]="trackByFn"> 

这似乎起到了作用,但这本来可以更清楚地记录下来,因为我确信在 Angular 模板表单中向 mat-table 添加/删除行并不是一个不常见的操作,我敢肯定还有许多其他情况需要处理索引。乍一看,使用 let i= 索引结构似乎表明所有工作都已为您完成!

【讨论】:

    猜你喜欢
    • 2018-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多