0

I'm trying to sort my list-component that I've created with angular material.

<div style="width:30%;">
        <mat-nav-list matSort (matSortChange)="sortData($event)">
            <th mat-sort-header="stuff.name">Name</th>
            <mat-list-item *ngFor="let stuff of vehicleDetails">
                <button matLine (click)="updateInfo(stuff.id)"> {{ stuff.name }} </button>
                <button mat-icon-button id="btn" *ngIf='check(stuff.alarm)' matTooltip="{{stuff.alarm[tooltipIndex(stuff)]?.timestamp}} - {{stuff.alarm[tooltipIndex(stuff)]?.description}}">
                    <mat-icon>info</mat-icon>
                </button>
            </mat-list-item>
        </mat-nav-list>
    </div>

The data displayed in the list is a bunch of vehicle names. It comes from my vehicleDetails which is an array of type VehicleDetail, containing properties such as name, id, etc. Right now I'm trying to sort by name. Im using the following functions when trying to achieve this functionality:

 export class VehiclelistComponent implements OnInit, AfterViewChecked
 {

vehicleDetails: VehicleDetail[] = [];
sortedVehicleDetails: VehicleDetail[];

sortData(sort: Sort) {
    const data = this.vehicleDetails.slice();
    if (!sort.active || sort.direction === '') {
      this.sortedVehicleDetails = data;
      return;
    }
    this.sortedVehicleDetails = data.sort((a, b) => {
      const isAsc = sort.direction === 'asc';
      switch (sort.active) {
        case 'name':
          return this.compare(a.name, b.name, isAsc);
        default:
          return 0;
      }
    });
  }

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

My ngOnInit and ngAfterViewChecked looks like this

ngOnInit() {
    // Init vehicles
    this.getVehicleDetails();

   }

  ngAfterViewChecked() {
    this.sortedVehicleDetails = this.vehicleDetails.slice();
  }

How can I solve my problem so I can sort by name or any other properties?

1 Answer 1

2

You need to also get the property by which the object array needs to be sorted.

Something like this

  sort(value: any[], criteria: SortCriteria): any[] {        
    if (!value || !criteria)
      return value;

    let p: string = criteria.property;

    let sortFn:(a: any, b: any) => any = (a, b) => {
      let value: number = 0;
      if (a[p] === undefined) value = -1;
      else if (b[p] === undefined) value = 1;
      else value = a[p] > b[p] ? 1 : (b[p] > a[p] ? -1 : 0);
      return criteria.descending ? (value * -1) : value;
    };

    value.sort(sortFn);
    return value;
  }

Where SortCriteria is,

interface SortCriteria {
  property: string;
  descending?: boolean;
}

You can also create a pipe so that you can use it directly in a template

Stackblitz

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.