Угловая таблица материалов - индекс строки не согласован - PullRequest
1 голос
/ 24 октября 2019

ТЛ; др;- см. мой ответ ниже;решение состоит в том, чтобы предоставить функцию trackBy

У меня есть простое приложение для составления расписания, использующее mat-table, где пользователь может добавлять часы, отработанные для каждого дня недели.

Добавление и удаление добавления строк в определенных последовательностях не работает.

Действия по воспроизведению проблемы:

Добавить новую строку, установленную в воскресенье на 1 Добавить другую строку и установить в воскресенье значение 2 Удалить первую строку - теперь будет одна строка с воскресеньем = 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;
  }



}

1 Ответ

0 голосов
/ 28 октября 2019

Проблема заключается в использовании индекса для создания уникального атрибута имени (атрибут имени требуется при использовании 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}}">

Кажется, что добавление и удалениеэлементы в / из источника данных не обновляют индекс обновления последовательно, и в моем сценарии я получаю две записи с одинаковым индексом.

Решение состоит в том, чтобы указать функцию trackBy, как указано в документация

В моем случае я добавил это в файл .ts:

  trackByFn(index, item) {
return index;

}

И в разметке:

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

Это, похоже, помогло, но это могло бы быть гораздо более четко задокументировано, так как я уверен, что добавление / удаление строк в / из таблицы mat в шаблоне с угловыми шаблонами не совсем необычная операция, и я уверен, чтоЕсть много других сценариев, где вам нужно иметь указатель на индекс. На первый взгляд, использование конструкции let i = index позволяет предположить, что вся работа выполнена за вас!

...