przemlat
przemlat

Reputation: 51

OrderBy pipe in angular 4

I'm trying to write sorting pipe according to code in this link: http://www.advancesharp.com/blog/1211/angular-2-search-and-sort-with-ngfor-repeater-with-example Although I have trouble with dealing with undefined values. My pipe works correctly on columns where there are not any undefined values. But when there is at least one undefined value in column pipe work in a strange way. My code below:

html template:

*ngFor="let candidate of filteredList | orderBy:{property: column, direction: direction}"

in html template to choose column and direction eg:

<th class="pointer" nowrap="nowrap" (click)="sort('lastName')">{{ 'candidates.candidates' | translate }}
      <i class="fa" [ngClass]="{'fa-sort': column != 'lastName',
                        'fa-sort-asc': (column == 'lastName' && !isDesc),
                        'fa-sort-desc': (column == 'lastName' && isDesc) }"
         aria-hidden="true"> </i></th>

order-by.pipe.ts

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

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

  transform(candidates: Array<object>, args?: any): any {
    candidates = candidates || [];
    return candidates.sort(function (a, b) {

      if (a[args.property] === b[args.property]) {
        return 0;
      }
      if (a[args.property] === '' || a[args.property] === null || typeof a[args.property] === 'undefined') {
        return 1;
      }
      if (b[args.property] === '' || b[args.property] === null || typeof b[args.property] === 'undefined') {
        return -1;
      }
      if (a[args.property] < b[args.property]) {
        console.log(a[args.property] + ' wartosc property');
        return -1 * args.direction;
      } else if (a[args.property].toLowerCase() > b[args.property].toLowerCase()) {
        return 1 * args.direction;
      } else {
        return 0;
      }
    });
  }
}

component.ts:

public sort(property: string) {
    this.isDesc = !this.isDesc;
    this.column = property;
    this.direction = this.isDesc ? 1 : -1;
  }

I was trying many different approaches but none of then was worinkg fine.

Upvotes: 4

Views: 11284

Answers (3)

Ali Adravi
Ali Adravi

Reputation: 22743

It will work even for null, undefined '' and any type of data type like number string bool:

transform(arr: any[], property: any, direction: number): any[] | null {

    if(!arr || arr?.length == 0)
      return arr;

      arr.sort((a: any, b: any) => {
      let v1 = a[property]?? '';
      let v2 = b[property]?? '';
      if(v1 < v2)
        return 1 * direction;
      else if(v1 > v2)
        return -1 * direction;
      else 
        return 0 * direction;
    });
    return arr;
  }

Upvotes: 0

Iaroslav
Iaroslav

Reputation: 295

Maybe that's because JavaSctipt Array.sort function will always put undefined to the end of array and the undefined values aren't passed to compareFunction as a and b arguments.

See this post for more details: javascript array.sort with undefined values

Upvotes: 0

Samuel Shyu
Samuel Shyu

Reputation: 151

Can you use lodash for sorting?

import { Pipe, PipeTransform } from '@angular/core';
import * as _ from 'lodash';

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

    transform(array: Array<{}>, args: string[]): Array<string> | Array<{}> {

        array = array || [];

        if (typeof args === 'undefined' || args.length !== 2) {
            return array;
        }

        const [key, direction] = args;

        if (direction !== 'ASC' && direction !== 'DESC') {
            return array;
        }

        return _.orderBy(array, (item:any) => item[key], direction.toLowerCase());
    }
}

Upvotes: 0

Related Questions