Lorsque vous utilisez le Angular keyvalue pipe pour itérer sur les propriétés d'un objet, comme suit:
<div *ngFor="let item of object | keyvalue">
{{item.key}}:{{item.value}}
</div>
J'ai rencontré un problème où les propriétés n'étaient pas itérées dans l'ordre attendu. Et ce commentaire suggère que je ne suis pas le seul à faire l'expérience de ce problème:
Comment boucler les propriétés d'un objet avec ngFor dans Angular
Quelqu'un peut-il indiquer ce qui détermine l'ordre d'itération lors de l'utilisation du canal de valeur de clé et comment forcer un ordre d'itération spécifique? Mon ordre d'itération idéal est l'ordre dans lequel les propriétés ont été ajoutées.
Merci
Selon Angular documentation , le canal keyvalue
trie les éléments par ordre key
par défaut. Vous pouvez fournir une fonction de comparaison pour modifier l'ordre de tri, mais elle ne prend en compte que les propriétés key
et value
, et non l'ordre d'entrée.
Par exemple, les fonctions de comparateur suivantes trient les éléments par ordre de valeur croissante et par ordre de clé inverse, respectivement:
valueAscOrder = (a: KeyValue<number,string>, b: KeyValue<number,string>): number => {
return a.value.localeCompare(b.value);
}
keyDescOrder = (a: KeyValue<number,string>, b: KeyValue<number,string>): number => {
return a.key > b.key ? -1 : (b.key > a.key ? 1 : 0);
}
lorsqu'il est appliqué au tuyau keyvalue
:
<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>
Voir ce stackblitz pour une démo.
Oui, les propriétés Object
effectuent une itération aléatoire, car elles ne sont pas stockées sous la forme array
en mémoire. Cependant, vous pouvez trier par propriétés.
Si vous souhaitez effectuer une itération par position d'insertion, vous devez créer une propriété supplémentaire, telle que index
, définir le timestamp
et trier par index
.
Vous trouverez ci-dessous le canal que vous pouvez utiliser pour contrôler le tri et l'itération.
Tuyau
import {Pipe, PipeTransform} from 'angular2/core';
@Pipe({name: 'values'})
export class ValuesPipe implements PipeTransform {
transform(value: any, args?: any[]): Object[] {
let keyArr: any[] = Object.keys(value),
dataArr = [],
keyName = args[0];
keyArr.forEach((key: any) => {
value[key][keyName] = key;
dataArr.Push(value[key])
});
if(args[1]) {
dataArr.sort((a: Object, b: Object): number => {
return a[keyName] > b[keyName] ? 1 : -1;
});
}
return dataArr;
}
}
Usage
<div *ngFor='#item in object | values:"keyName":true'>...</div>
Ceci est identique à la réponse acceptée, mais il a un objet plus complexe, ce qui peut aider quelqu'un à trier par champ d'index personnalisé et à l'aide du tube keyval.
En composante angulaire:
myObject = {
"key1": { val:"whateverVal1", code:"whateverCode1", index: 1},
"key2": { val:"whateverVal2", code:"whateverCode2", index: 0},
"key3": { val:"whateverVal3", code:"whateverCode3", index: 2}
}
Fonction de tri dans le composant:
indexOrderAsc = (akv: KeyValue<string, any>, bkv: KeyValue<string, any>): number => {
const a = akv.value.index;
const b = bkv.value.index;
return a > b ? 1 : (b > a ? -1 : 0);
};
dans le modèle:
<div *ngFor="let x of myObject | keyvalue:indexOrderAsc">
...
</div>