DP3
DP3

Reputation: 128

Angular 2 Sort table columns

I am trying to sort my columns of my table using Angular 2

the pipe transform code is

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({  name: 'orderBy' })
export class OrderByPipe implements PipeTransform {

  transform(records: Array<any>, args?: any): any {

    return records.sort(function(a, b){
      if(a[args.property] < b[args.property]){
        return -1 * args.direction;
      }
      else if( a[args.property] > b[args.property]){
        return 1 * args.direction;
      }
      else{
        return 0;
      }
    });
  };
}

I have defined a sort function in component.ts file as following as :

  sort(property){
    this.isDesc = !this.isDesc; //change the direction
    this.column = property;
    this.direction = this.isDesc ? 1 : -1;
    //this.sort(this.column);
  };

HTML looks like this

 <th class="cell-width-header title" (click)="sort(sellerNo)">
            Seller No
            <i class="fa" [ngClass]="{'fa-sort': column != 'sellerNo', 'fa-sort-asc': (column == 'sellerNo' && isDesc), 'fa-sort-desc': (column == 'sellerNo' && !isDesc) }" aria-hidden="true"> </i>
          </th>




 <tr *ngFor="let x of selectedData  | orderBy: {property: column, direction: direction}">


            <td>{{x.sellerNo}}</td>

but after loading the page, I get following error

zone.js:522 Unhandled Promise rejection: Error in ./FundingRequestComponent class FundingRequestComponent - inline template:208:14 caused by: Cannot read property 'sort' of undefined ; Zone: angular ; Task: Promise.then ; Value: ViewWrappedError {__zone_symbol__error: Error: Error in ./FundingRequestComponent class FundingRequestComponent - inline template:208:14 cau……} Error: Error in ./FundingRequestComponent class FundingRequestComponent - inline template:208:14 caused by: Cannot read property 'sort' of undefined at ViewWrappedError.ZoneAwareError (http://localhost:4200/polyfills.bundle.js:6688:33) at ViewWrappedError.BaseError [as constructor] (http://localhost:4200/vendor.bundle.js:94913:16) at ViewWrappedError.WrappedError [as constructor] (http://localhost:4200/vendor.bundle.js:94978:16) at new ViewWrappedError (http://localhost:4200/vendor.bundle.js:96282:16)

Upvotes: 0

Views: 7276

Answers (1)

Tomek Sułkowski
Tomek Sułkowski

Reputation: 7201

I assume you are loading the data (selectedData) for this template asynchronously in the component's class, so at the start it's not yet returned form the service, hence selectedData = undefined.

There are several things you can do to mitigate that:

1. Initialize the data in the component

Set the selectedData class property to an empty array so when the pipe runs its input will be an array even if the backend data is not yet returned.

export class MyComponent {
    selectedData = [];
}

2. Prevent evaluation of this part of the template with *ngIf

Don't render the template part with said pipe until you have the array.

<table *ngIf="selectedData">
  <!-- ... -->
  <tr *ngFor="let x of selectedData  | orderBy: {property: column, direction: direction}">
</table>

3. Make the pipe "empty-input-safe" by providing a default input

This should be the preferred solution because with that you won't have to remember to employ any special logic (like ver. 1 or ver. 2) each time you're using this pipe somewhere.

@Pipe({  name: 'orderBy' })
export class OrderByPipe implements PipeTransform {
  transform(records: Array<any> = [], args?: any): any {
    /* ... */

See the records = [] default in the transform's method parameter?

I try to use this as a general rule of thumb to always prepare the pipe for getting no input initially. Makes a lot of headaches go away :)

Upvotes: 1

Related Questions