web-dev-qa-db-fra.com

valeur de clé angulaire propriétés de tri/itérer dans l'ordre

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

2
danday74

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.

10
ConnorsFan

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>
1
Sunil Singh

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>
1
Peter Dub