Angular中选中mat-select选项后如何将size加载到对应行的td
问题根源
- 所有行的
mat-select共用了同一个dataCtrl、dataFilterCtrl实例,导致不同行的下拉状态互相干扰。 - 选中值存储逻辑错误:
onSelect方法将选中项按选择顺序push到OptionSelected数组,和行索引没有绑定,页面按行索引i读取OptionSelected[i]时自然无法匹配到对应的行。 @ViewChild('singleSelect')只能匹配到页面第一个下拉实例,无法支持多行动态生成的下拉组件。
改造方案
1. TS代码调整
import { FormArray, FormControl } from '@angular/forms'; // 其他原有导入保持不变 dataTitles: any = DataTitles; dataDetails: any = DataDetails; // 替换原有单个control为数组,对应每一行的下拉 dataCtrlArray: FormArray = new FormArray([]); dataFilterCtrlArray: FormControl[] = []; filteredData: ReplaySubject<any> = new ReplaySubject<any>(1); // 移除原有全局的singleSelect ViewChild _onDestroy = new Subject<void>(); ngOnInit() { // 为每一行初始化独立的控制实例 this.dataDetails.forEach(() => { this.dataCtrlArray.push(new FormControl()); this.dataFilterCtrlArray.push(new FormControl()); }); this.filteredData.next(this.dataTitles.slice()); // 搜索逻辑调整为监听所有搜索控件的变化 this.dataFilterCtrlArray.forEach(ctrl => { ctrl.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 = []; // 新增入参rowIndex接收当前选中的行索引 onSelect(option: any, rowIndex: number) { var objIndex = this.dataTitles.findIndex(x => x.id == option.id); if (this.dataTitles[objIndex].title !== 'None') { this.dataTitles[objIndex].condition = 1; } // 直接将选中值写入对应行索引的位置,替换原有push逻辑 this.OptionSelected[rowIndex] = { id: option.id, size: option.size }; // 原有去重逻辑如果需要保留,可在此处补充校验其他行是否已选中当前option console.log(this.OptionSelected); } filterData() { if (!this.dataTitles) { return; } // 搜索逻辑保持不变,所有行共用同一份过滤后的选项列表 let search = this.dataFilterCtrlArray.find(ctrl => ctrl.value)?.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 ) ); }
2. 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"> <!-- 绑定当前行对应的formControl --> <mat-select [formControl]="dataCtrlArray.at(i)" placeholder="Select" [compareWith]="compareItems"> <mat-option> <!-- 绑定当前行对应的搜索control --> <ngx-mat-select-search [formControl]="dataFilterCtrlArray[i]"></ngx-mat-select-search> </mat-option> <mat-option *ngFor="let op of filteredData | async" [value]="op.id" (click)="onSelect(op, i)" [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>
内容的提问来源于stack exchange,提问作者Emy
相关产品推荐
相关产品推荐

