After search button is clicked in header field, this page (component below) is called. and then I can click sort button on "parameterName" column. Sort button works perfectly. but after I click search button while sort button is active, rendered page's order column's sort not working, parameterName column sort works though.

I am stack here, have no idea to solve this problem.

I need your help.

this is my expect

| parameterName | display | order |
----------------------------------------------
| CJ191IKI | true | 2 |
-----------------------------------------------
| CJ191CK | true | 1 |
-----------------------------------------------
| CJ1077 | true | 3 |

but result is below

| parameterName | display | order |
----------------------------------------------
| CJ191IKI | true | 1 |
-----------------------------------------------
| CJ191CK | true | 2 |
-----------------------------------------------
| CJ1077 | true | 3 |

childForm

childForm: FormGroup
  controls: {parameters: FormArray},
  value: 
    parameters: Array
      0:
        display: true,
        order: "1",
        parameterName: "CJ191CK",
      1: 
        display: true,
        order: "2",
        parameterName: "CJ191IKI",
      2:
        display: true,
        order: "3",
        parameterName: "CJ1077"

html

<form [formGroup]="childForm">
  <div>
    <div
  [ngClass]="{'no-scroll': disabledScroll}">
      <table
        mat-table
        [dataSource]="dataSource"
        matSort
        matSortDisableClear
        formArrayName="parameters"
      >
        <ng-container matColumnDef="parameterName">
          <th mat-header-cell *matHeaderCellDef mat-sort-header>
            {{ 'PARAMETER' | translate }}
          </th>
          <td mat-cell *matCellDef="let element">{{ element.parameterName }}</td>
        </ng-container>
        <ng-container matColumnDef="display">
          <th mat-header-cell *matHeaderCellDef>
            {{ 'DISPLAY' | translate }}
          </th>
          <td mat-cell *matCellDef="let element; let index = index" [formGroupName]="index" class="mat-column-display">
            <mat-radio-group formControlName="display">
              <mat-radio-button value="true" (change)="radioValueChanged(element, $event)" [checked]="element.display">{{ 'RADIO_ON' | translate }}</mat-radio-button>
              <mat-radio-button value="false" (change)="radioValueChanged(element, $event)" [checked]="!element.display">{{ 'RADIO_OFF' | translate }}</mat-radio-button>
            </mat-radio-group>
          </td>
        </ng-container>
        <ng-container matColumnDef="order">
          <th mat-header-cell *matHeaderCellDef>
            {{ 'ORDER' | translate }}
          </th>
          <td mat-cell *matCellDef="let element; let index = index">
            <mat-form-field [formGroupName]="index">
              <input matInput type="text" (keyup)="valueChanged(element, $event, $event.target.value)" formControlName="order" />
            </mat-form-field>
          </td>
        </ng-container>

        <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
        <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
      </table>
      <div *ngIf="false">No records found</div>
    </div>
    <div><mat-spinner [diameter]="100" *ngIf="loading"></mat-spinner></div>
  </div>
</form>

Component

@Input()
childForm: FormGroup;

get form(): FormGroup {
  return this._form;
}
_form: FormGroup;

get dataSource() {
  return this._dataSource;
}
private _dataSource: CustomDataSource;

ngOnInit() {
  this.initForm();
  this._dataSource = new CustomDataSource(this.childForm.controls['parameters'].value, this.sort);
} 

ngOnChanges(changes: SimpleChanges): void {
  if ('value' in changes) {
    if (this.dataSource && this.dataSource.data() && this.childForm.controls['parameters'].value) {
      this._dataSource.updateDataSource(this.childForm.controls['parameters'].value, this.sort);
    }
  }
}

initForm() {
  this._form = this.childForm;
}

DataSource

export class CustomDataSource extends DataSource<any> {
  private dataSubject = new BehaviorSubject<Parameter[]>([]);

  sort: MatSort;

  data() {
    return this.dataSubject.value;
  }

  update(data) {
    this.dataSubject.next(data);
  }

  constructor(data: Parameter[], _sort: MatSort) {
    super();
    this.sort = _sort;
    this.dataSubject.next(data);
  }

  updateDataSource(data: Parameter[], _sort: MatSort) {
    this.sort = _sort;
    this.dataSubject.next(data);
  }

  connect(collectionViewer: CollectionViewer): Observable<Parameter[]> {
    const displayDataChanges = [this.dataSubject, this.sort.sortChange];
    return merge(...displayDataChanges).pipe(
      map(() => {
        return this.sortData(this.dataSubject.getValue());
      })
    );
  }

  disconnect(collectionViewer: CollectionViewer) {
    this.dataSubject.complete();
  }

  compare(a: number | string, b: number | string, isAsc: boolean) {
    return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
  }

  sortData(parameter: Parameter[]): Parameter[] {
    const data = parameter;
    return data.sort((a, b) => {
      const isAsc = this.sort.direction === 'asc';
      switch (this.sort.active) {
        case 'parameterName':
          return this.compare(a.parameterName, b.parameterName, isAsc);
        default:
          return 0;
      }
    });
  }
}

0 Answers