You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mat-table自定义过滤对student_id/student_name列失效问题求助

Mat-table自定义过滤异常问题求助

Mat-table自定义过滤功能异常:student_id和student_name列无法触发过滤,CA(ca1、ca2等)数值列可正常过滤。

相关代码

Model定义

export class CassData {
    enroll_id: string;
    student_id: string;
    student_name: string;
    ca1: number;
    ca2: number;
    ca3: number;
    exam: number;
    total: number;

    static asFormGroup(cass: CassData): FormGroup {
        const fg = new FormGroup({
            enroll_id: new FormControl(cass.enroll_id),
            student_id: new FormControl(cass.student_id),
            student_name: new FormControl(cass.student_name),
            ca1: new FormControl(cass.ca1),
            ca2: new FormControl(cass.ca2),
            ca3: new FormControl(cass.ca3),
            exam: new FormControl(cass.exam),
            total: new FormControl(cass.total)
        });
        return fg;
    }
}

cass.component.ts文件

export class CassComponent implements OnInit, AfterViewInit, OnDestroy {

  dataSource: MatTableDataSource<any>;
  displayedColumns: string[] = ['student_id', 'student_name', 'ca1', 'ca2', 'ca3', 'exam', 
   'total', 'delete'];

  constructor(private _changeDetectorRef: ChangeDetectorRef, 
            private _formBuilder: UntypedFormBuilder,
            private _cassService: CassService
    ) { }

  ngOnInit(): void {
    // Create the form
    this.assessmentForm = this._formBuilder.group({
      term: [''],
      subject_code: [''],
      class_name: [''],
      cass: this._formBuilder.array([])
    });
  }

  getCassData(): void {

    this.isLoading = true;
    
    let sch_code = this.sch_code;
    let data = this.assessmentForm.getRawValue();

    this._cassService.getCassAsFormArray(sch_code, data).subscribe(cass => {

      if (cass.length > 0) {
        
        this.assessmentForm.setControl('cass', cass);

        this.dataSource = new MatTableDataSource((this.assessmentForm.get('cass') as FormArray).controls);

        this.dataSource.filterPredicate = (data: FormGroup, filter: string) => {
          return Object.values(data.controls).some(x => x.value == filter);
        };

        this.assessmentList = true;

        this.dataSource.sort = this._sort;
        this.isLoading = false;
      } 
      else {
        this.isLoading = false;
        this.assessmentList = false;
      }

      // Mark for check
      this._changeDetectorRef.markForCheck();

    });
  }

  applyFilter(filterValue: string) {
    this.dataSource.filter = filterValue.toLowerCase();
  }

}

cass.component.html文件

<div class="w-full">
  <form [formGroup]="assessmentForm">
   <button 
    (click)="getCassData()"
    mat-stroked-button>
    <span class="ml-1">Load Data</span>
   </button>
   <input matInput (keyup)="applyFilter($event.target.value)" 
   [autocomplete]="'off'" 
   [placeholder]="'Search students'"
   [disabled]="!assessmentList" #searchField>
  </form>
  
  <ng-container *ngIf="assessmentList; else noData">
    <ng-container formArrayName="cass">
        <table mat-table [dataSource]="dataSource" matSort>
            <!-- ID Column -->
            <ng-container matColumnDef="student_id">
                <th mat-header-cell mat-sort-header *matHeaderCellDef> ID </th>
                <td mat-cell *matCellDef="let element">
                    {{element.get('student_id').value}}
                </td>
            </ng-container>
                            
            <!-- Name Column -->
            <ng-container matColumnDef="student_name">
                <th mat-header-cell mat-sort-header *matHeaderCellDef> Name </th>
                <td mat-cell *matCellDef="let element">
                    {{element.get('student_name').value}}
                </td>
            </ng-container>
                            
            <!-- CA1 Column -->
            <ng-container matColumnDef="ca1">
                <th mat-header-cell mat-sort-header *matHeaderCellDef> CA1 (10%)</th>
                <td mat-cell *matCellDef="let element" [formGroup]="element">
                    <mat-form-field>
                        <input type="number" formControlName="ca1" matInput>
                    </mat-form-field>
                </td>
            </ng-container>
                            
            <!-- CA2 Column -->
            <ng-container matColumnDef="ca2">
                <th mat-header-cell mat-sort-header *matHeaderCellDef> CA2 (10%)</th>
                <td mat-cell *matCellDef="let element" [formGroup]="element">
                    <mat-form-field>
                        <input type="number" formControlName="ca2" matInput>
                    </mat-form-field>
                </td>
            </ng-container>
            
            ...
            
        </table>
      </ng-container>
   </ng-container>

</div>

问题原因及解决方案

问题根源

  1. 匹配逻辑错误:原filterPredicate使用==做严格相等匹配,只有输入内容与控件值完全一致时才会命中,不符合用户搜索部分内容的需求,导致字符串列无法匹配。
  2. 大小写不统一:applyFilter中将过滤关键词转为小写,但student_id、student_name的控件值未做小写转换,大小写不一致时无法匹配。
  3. 类型不兼容:数值列(ca1等)的数值与字符串过滤词用==时会隐式转换,所以能正常匹配;但字符串列没有这个转换,导致匹配失败。

修复代码

修改getCassData中的filterPredicate逻辑:

this.dataSource.filterPredicate = (data: FormGroup, filter: string) => {
  // 将每个控件的值转为字符串并统一小写,判断是否包含过滤关键词
  return Object.values(data.controls).some(control => {
    const value = control.value?.toString().toLowerCase() || '';
    return value.includes(filter);
  });
};

说明

  • 所有控件值转为字符串并小写,确保与过滤词大小写统一;
  • 使用includes实现包含匹配,符合用户搜索部分内容的需求;
  • 兼容数值和字符串类型的控件值,解决类型不匹配问题。

内容的提问来源于stack exchange,提问作者HardSoft

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 21:01:02