Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angular keyvalue pipe sort properties / iterate in order

When using the Angular keyvalue pipe to iterate over an object's properties as follows:

<div *ngFor="let item of object | keyvalue">
  {{item.key}}:{{item.value}}
</div>

I have experienced an issue where the properties were not iterated in the order expected. And this comment suggests that I am not the only one to experience this issue:

How to loop over object properties with ngFor in Angular

Can someone advise what determines the order of iteration when using the keyvalue pipe please and how to force a specific iteration order? My ideal order of iteration is the order in which the properties were added.

Thanks

like image 657
danday74 Avatar asked Oct 13 '18 14:10

danday74


3 Answers

According to the Angular documentation, the keyvalue pipe sorts the items by key order by default. You can provide a comparer function to change that order, and sort the items according to the key, to the value, or to the entry order of the properties in the object.

The following comparer functions sort the items in various orders:

// Preserve original property order
originalOrder = (a: KeyValue<number,string>, b: KeyValue<number,string>): number => {
  return 0;
}

// Order by ascending property value
valueAscOrder = (a: KeyValue<number,string>, b: KeyValue<number,string>): number => {
  return a.value.localeCompare(b.value);
}

// Order by descending property key
keyDescOrder = (a: KeyValue<number,string>, b: KeyValue<number,string>): number => {
  return a.key > b.key ? -1 : (b.key > a.key ? 1 : 0);
}

when applied to the keyvalue pipe:

<div *ngFor="let item of object | keyvalue: originalOrder">
  {{item.key}} : {{item.value}}
</div>

<div *ngFor="let item of object | keyvalue: valueAscOrder">
  {{item.key}} : {{item.value}}
</div>

<div *ngFor="let item of object | keyvalue: keyDescOrder">
  {{item.key}} : {{item.value}}
</div>

See this stackblitz for a demo.


Supplying a constant or null instead of a valid comparer function preserves the entry order of the object properties, like originalOrder does, but it causes an exception (see this stackblitz):

<!-- The following syntaxes preserve the original property order -->
<div *ngFor="let item of object | keyvalue: 0">
<div *ngFor="let item of object | keyvalue: 374">
<div *ngFor="let item of object | keyvalue: null">

<!-- but they cause an exception (visible in the console) -->
ERROR TypeError: The comparison function must be either a function or undefined

Moreover, using that syntax twice in the template does not display the items at all. Therefore, I would not recommend it. Please note that supplying undefined as the comparer function does not cause any exception but does not change the default behavior: the items are sorted by key value.

like image 104
ConnorsFan Avatar answered Oct 24 '22 00:10

ConnorsFan


<div *ngFor="let item of object | keyvalue: 0">
  {{item.key}} : {{item.value}}
</div>

directly write and you will get the data in sameorder as it is in the json

keyvalue: 0
like image 31
V_for_Vj Avatar answered Oct 24 '22 00:10

V_for_Vj


Yes, by default the keyvalue pair sorting data in ascending order.

To keep it unsorted modify as:

keyvalue: 0

Final code:

<div *ngFor="let item of object | keyvalue:0">
  {{item.key}}:{{item.value}}
</div>

But for angular 7 or above, you need to put an empty function to keep data unsorted.

<div *ngFor="let item of object | keyvalue: unsorted">
      {{item.key}}:{{item.value}}
    </div>

In your .ts file just put this empty function.

  unsorted() { }

Hope it's helpful.

like image 27
Majedur Avatar answered Oct 23 '22 23:10

Majedur