在标记选项的同一行的 td 中加载数据

Load data in a td of the same row where an option is marked

为了演示这个问题,我有一个 table,其中显示了详细信息列表和几个 mat-select,当 select 选择一个选项时,它的“大小”标记的选项在 td 中加载。

问题是它不会在 selected 选项所在的同一行中加载“大小”。我怎么能得到这个?尺寸显示在 td 中,但按从上到下的顺序排列。

例如,如果没有标记的选项,我 select 第 3 行的一个选项。该选项的“大小”将加载到第一行,如果我在任何其他行标记一个选项数据按照行的顺序加载。

我在 stackblitz 中有演示:DemoStackblitz

HTML

<table class="table">
  <tr>
    <th>Titles</th>
    <th>Size</th>
    <th>Detail</th>
    <th>Duration</th>
  </tr>
  <tr *ngFor="let row of dataDetails let i = index">
    <td>
      <mat-form-field appearance="outline">
        <mat-select [formControl]="dataCtrl" placeholder="Select" [compareWith]="compareItems" #singleSelect>
          <mat-option>
            <ngx-mat-select-search [formControl]="dataFilterCtrl"></ngx-mat-select-search>
          </mat-option>
          <mat-option *ngFor="let op of filteredData | async" [value]="op.id" (click)="onSelect(op)"
            [disabled]="op.condition===1">
            {{op.title}}
          </mat-option>
        </mat-select>
      </mat-form-field>
    </td>
    <td>{{OptionSelected[i]?.size}}</td>
    <td>{{row.detail}}</td>
    <td>{{row.duration}}</td>
  </tr>
</table>

TS

  dataTitles: any = DataTitles;
  dataDetails: any = DataDetails;
  dataCtrl: FormControl = new FormControl();
  dataFilterCtrl: FormControl = new FormControl();
  filteredData: ReplaySubject<any> = new ReplaySubject<any>(1);
  @ViewChild('singleSelect', { static: true }) singleSelect: MatSelect;

  _onDestroy = new Subject<void>();

  ngOnInit() {
    this.dataCtrl.setValue(this.dataDetails[0]);
    this.filteredData.next(this.dataTitles.slice());
    this.dataFilterCtrl.valueChanges
      .pipe(takeUntil(this._onDestroy))
      .subscribe(() => {
        this.filterData();
      });
  }
  compareItems(i1: any, i2: any) {
    return i1 && i2 && i1.key === i2.key;
  }
  ngOnDestroy() {
    this._onDestroy.next();
    this._onDestroy.complete();
  }
  OptionSelected: any = [];
  onSelect(option: any) {
    var objIndex = this.dataTitles.findIndex(x => x.id == option.id);
    if (this.dataTitles[objIndex].title !== 'None') {
      this.dataTitles[objIndex].condition = 1;
    }
    if (this.OptionSelected.length === 0) {
      this.OptionSelected.push({ id: option.id, size: option.size });
    } else {
      let check = this.OptionSelected.map((item: any) => item.id).includes(
        option.id
      );
      if (check === false) {
        this.OptionSelected.push({ id: option.id, size: option.size });
      }
    }
    console.log(this.OptionSelected);
  }
  filterData() {
    if (!this.dataTitles) {
      return;
    }
    let search = this.dataFilterCtrl.value;
    if (!search) {
      this.filteredData.next(this.dataTitles.slice());
      return;
    } else {
      search = search.toLowerCase();
    }
    this.filteredData.next(
      this.dataTitles.filter(
        (x: any) => x.title.toLowerCase().indexOf(search) > -1
      )
    );
  }

问题

您在调用期间将当前选择的值推入 OptionSelected onSelect。这会导致所选行数据与实际显示数据的行不匹配。

伪代码示例:

Select TitleA in Row 4
Push new Data into OptionSelected
OptionSelected[0]?.size displays data in the first row 

解决方案

您已经在此处使用模板变量 #singleSelect 跟踪当前所选值的值:

<mat-select ... #singleSelect>

<mat-select> 组件有一个值输入。

@Input()
value: any Value of the select control.

因此您可以通过简单地使用模板 ref 来显示当前值:

<td>{{singleSelect.value}}</td>

Stackblitz example