2

I am trying to implement sorting / filtering on angular material table with formArray as input data source.

StackBlits code link

dataSource = new MatTableDataSource([]);
<table mat-table [dataSource]="formdataarray.controls" multiTemplateDataRows class="mat elevation-z8" matSort >
<ng-container  matColumnDef="{{column}}" *ngFor="let column of columnsToDisplay" >
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{column}}</th>
<td mat-cell *matCellDef="let element"> {{ element.value[column] }}  </td>
</ng-container>

But Sorting / Filtering is not working

4 Answers 4

5

You have two options here:

  • use plain array formdataarray.controls as a dataSource and implement all DataSource methods like filter, sort by your own. Or write custom CDK DataSource implementation. See also https://blog.angular-university.io/angular-material-data-table/

  • use MatTableDataSource and adjust filtering and sorting logic to support AbstractControl object.

html

<table mat-table [dataSource]="dataSource"

ts

ngOnInit() {
  // fill FormArray
  ...
  this.dataSource.data = this.formdataarray.controls;
  this.dataSource.sortingDataAccessor = (data: AbstractControl, sortHeaderId: string) => {
    const value: any = data.value[sortHeaderId];
    return typeof value === 'string' ? value.toLowerCase() : value;
  };

  const filterPredicate = this.dataSource.filterPredicate;
  this.dataSource.filterPredicate = (data: AbstractControl, filter) => {
    return filterPredicate.call(this.dataSource, data.value, filter);
  }
}

Forked Stackblitz

Also, if you want to add new items to your FormArray you should update this.dataSource.data as well. See also Angular Material editable table using FormArray

Sign up to request clarification or add additional context in comments.

Comments

0

You also needs add event (matSortChange)=sortTable($event)

To the table tag

And add sortTable logic inside components

1 Comment

Hi I added this event but its still not working can you show on stackblitz.com/github/snehalp29/angular-expand-row
0

Requires ngAfterViewInit to work

import { MatTableDataSource } from '@angular/material/table';
import { MatSort } from '@angular/material/sort';

...

@ViewChild(MatSort, {static: false}) sort: MatSort

...

ngOnInit() {
  this.getYourData$.subscribe(d => this.data = new MatTableDataSource(d));
}

ngAfterViewInit(): void {

  this.data.sortingDataAccessor = (data: AbstractControl, sortHeaderId: string) => {
  const value: any = data.value[sortHeaderId];
  return typeof value === 'string' ? value.toLowerCase() : value;
};

this.data.sort = this.sort; // where this.sort defined above.

  this.data.filterPredicate = (data: AbstractControl, filter) => {
  // return true or false on data.
  }
}


... html

<table matSort ...

Comments

0

If you choose the option to use the controls (here FormGroups) of the FormArray as the data for the MatTableDataSource you can use this snippet to get the sorting and filtering working.

<div [formGroup]="tableFormGroup">
  <table mat-table matSort matSortDirection="desc" [dataSource]="dataSource" [formArrayName]="formArrayName">
  <!-- Price Column -->
    <ng-container matColumnDef="price">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>Price</th>
      <td mat-cell *matCellDef="let row; let index = dataIndex" [formGroupName]="getArrayIndex(row)">
        <mat-form-field class="mat-input-table" [appearance]="'fill'" [subscriptSizing]="'dynamic'">
          <input matInput [formControlName]="'price'">
        </mat-form-field>
      </td>
    </ng-container>
<!-- [...] -->
//component.ts
getArrayIndex(row: FormGroup<TableItemForm>): number {
  return this.dataSource.filteredData.findIndex((value: FormGroup<TableItemForm>): boolean =>
    row.controls.id.value === value.controls.id.value)
}

Ensure that the "id" control values in the formGroups are unique across the entire formArray. This approach may not be the most efficient since getArrayIndex is called each time you hover over a row element, but it functions as expected. For a more detailed description of the task, please refer this article here.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.