2

I have the following ngFor statement and I want to sort by price. https://plnkr.co/edit/DC8I8DRB5UKhvWf6Sppl?p=preview

<div *ngFor="let coin of keys(); let i = index;">{{feeds[coin].price}}</div>

export class PricingTableComponent{

  public feeds:  FeedItemDictionary = {};

  constructor(service: PricingApiService,private route:ActivatedRoute) {   

      this.feeds["btc"] = {price : 1,coin : "BitCoin"} ;
      this.feeds["eth"] = {price : 2,coin : "Etherium"} ;
      //... 1300 like this...
    });
  }

  keys() {
    return Object.keys(this.feeds);
  }
}

interface FeedItemDictionary {
  [ index: string ]: FeedItem // price and coin memebers
}

the problem is that this is a dictionary (I must use a dictionary or map).
Is it possible to sort by value member?
Can you please fix my example in plnkr?
Thanks

SexyMF
  • 10,657
  • 33
  • 102
  • 206

3 Answers3

4

First of all, I wouldn't call a method in the template, why? This means that this method will be called on each change detection, which is often: *ngFor running an infinite loop in angular2 In worst case this can crash your browser.

You could use a pipe to order, but I wouldn't use that, also mention in the docs why there isn't an inbuilt order or filter pipe: https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe

What I would do, is handle all the business logic in the component, and then just iterate an array in template. So I'd first make your data iterable as well as sorting it:

ngOnInit() {
  let keyArr: any[] = Object.keys(this.feeds)
  keyArr.forEach((key: any) => {
    // push object with abbreviation, price and coin to array
    this.myArray.push({ abbrv: key, price: this.feeds[key].price, coin: this.feeds[key].coin });
  });
  // ASC
  this.myArray = this.myArray.sort((a, b) => a.price - b.price)
}

With this you end up with an array like:

[{abbrv: "eth", price: 54115, coin: "Etherium"}, ....]

and in your template you would just then iterate myArray:

<div *ngFor="let item of myArray">
  {{item.abbrv}} = {{item.price}}
</div>

StackBlitz

AT82
  • 71,416
  • 24
  • 140
  • 167
  • Thank you. The thing is, the array is actually lined with a socket, and evey 0.05 second there is a change in the array. So, in your way. is it going to work for me? Thanks again – SexyMF Dec 30 '17 at 14:44
0

To sort by the coin string, change your keys function to the following:

keys()  {
   return Object
     .keys(this.feeds)
     .sort((a, b) => this.feeds[a].coin.localeCompare(this.feeds[b].coin));
}

If, however, you want to sort by the value of price (ascending), then change it to the following:

keys()  {
   return Object
     .keys(this.feeds)
     .sort((a, b) => this.feeds[a].price - this.feeds[b].price));
}  
user184994
  • 17,791
  • 1
  • 46
  • 52
0

you can use a pipe:

@Pipe({
  name: 'SortBy'
})
export class IeSortPipe implements PipeTransform {

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

  if(args==='ASC')
    values = values.sort();
    else
    values = values.sort().reverse();

    return values;
  }
}

I added to your code the sort pipe:

https://plnkr.co/edit/L6Wk2GlsRb53RsNUeurx?p=preview

Jialzate
  • 315
  • 1
  • 6