web-dev-qa-db-ja.com

angular KeyValueパイプの並べ替えプロパティ/順番に繰り返す

Angular keyvalue パイプを使用して、次のようにオブジェクトのプロパティを反復処理する場合:

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

プロパティが期待した順序で繰り返されないという問題が発生しました。そして、このコメントは、この問題を経験したのは私だけではないことを示唆しています。

AngularのngForでオブジェクトプロパティをループする方法

誰かがキーバリューパイプを使用するときに反復の順序を決定するものと、特定の反復順序を強制する方法をアドバイスできますか?私の理想的な反復順序は、プロパティが追加された順序です。

ありがとう

37
danday74

Angular documentation によると、keyvalueパイプはデフォルトでkeyの順序でアイテムをソートします。比較関数を提供できますその順序を変更し、keyvalue、またはオブジェクト内のプロパティのエントリ順に従って項目を並べ替えます。

次の比較関数は、アイテムをさまざまな順序で並べ替えます。

// 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);
}

keyvalueパイプに適用した場合:

<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>

デモについては this stackblitz を参照してください。


有効な比較関数の代わりに定数またはnullを指定すると、originalOrderと同様にオブジェクトプロパティのエントリ順が保持されますが、例外が発生します( 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

さらに、テンプレートでその構文を2回使用しても、アイテムはまったく表示されません。したがって、私はそれをお勧めしません。比較関数としてundefinedを指定しても例外は発生しませんが、デフォルトの動作は変更されません。項目はkey値でソートされます。

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

直接書き込むと、jsonと同じ順序でデータが取得されます

keyvalue: 0
18
V_for_Vj

使用できるオブジェクトの順序を維持するには

keepOrder = (a, b) => {
    return a;
}

あなたが持っているとしましょう

wbs = {
"z": 123,
"y": 456,
"x": 789,
"w": 0#*
}

キー値を使用する場合、キーでアルファベット順に取得します

w 0#*
x 789
y 456
z 123

適用:keepOrderあなたはオブジェクトの順序を維持します

<ion-item *ngFor="let w of wbs | keyvalue: keepOrder">
    <ion-label>{{ w.key }}</ion-label>
    <ion-label>{{ w.value }}</ion-label>
</ion-item>
7
A. D'Alfonso

これは受け入れられた回答と同じですが、より複雑なオブジェクトを持っているため、カスタムインデックスフィールドで並べ替えたり、keyvalパイプを使用したりするのに役立ちます。

angular component:

myObject = {
    "key1": { val:"whateverVal1", code:"whateverCode1", index: 1},
    "key2": { val:"whateverVal2", code:"whateverCode2", index: 0},
    "key3": { val:"whateverVal3", code:"whateverCode3", index: 2}
}

コンポーネントのソート機能:

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);
    };

テンプレート内:

<div *ngFor="let x of myObject | keyvalue:indexOrderAsc">
    ...
</div>
7
Peter Dub

以下のコードを試してください:

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

はい。デフォルトでは、キーと値のペアは昇順でデータをソートします。

ソートしないでおくには、次のように変更します。

keyvalue: 0

最終コード:

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

ただし、angular 7以上の場合、空の関数を配置してデータを並べ替えないようにする必要があります。

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

あなたの.tsファイルは、この空の関数を置くだけです。

  unsorted() { }

お役に立てば幸いです。

3
Majedur Rahaman

はい、Objectプロパティはメモリにarrayとして格納されないため、ランダムに繰り返されます。ただし、プロパティで並べ替えることができます。

挿入位置で反復したい場合は、indexのような追加のプロパティを1つ作成し、timestampを設定してindexでソートする必要があります。

以下は、並べ替えと反復を制御するために使用できるパイプです

パイプ

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;
    }
}

使用法

<div *ngFor='#item in object | values:"keyName":true'>...</div>
2
Sunil Singh

パイプを作成して、デフォルトを無秩序に設定します。

// src/app/pipes/new-key-value.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
import { KeyValuePipe } from '@angular/common';
import { KeyValueDiffers } from '@angular/core';
const unordered = (a,b)=>0

@Pipe({
  name: 'newkeyvalue'
})

// This pipe uses the angular keyvalue pipe. but defaults to unordered.
export class NewKeyValuePipe implements PipeTransform {

  constructor(public differs: KeyValueDiffers){};
  public transform (value, compareFn = unordered){
    let pipe =  new KeyValuePipe(this.differs);
    return pipe.transform(value, compareFn)
  }
}

リンク:

パイプからAngular2パイプを呼び出すことはできますか?

https://github.com/angular/angular/blob/8.2.14/packages/common/src/pipes/keyvalue_pipe.ts#L25-L89

テンプレートの使用:

// src/app/some-component/some-component.html
<div *ngFor="let x of myObject | newkeyvalue>
</div>

module.tsに登録する

// src/app/app.module.ts
import { NewKeyValuePipe } from '@/pipes/new-key-value.pipe.ts'
...
@NgModule({
  declarations: [
    ...
    NewKeyValuePipe,
    ...
  ]
...
})
1
Michael Dimmitt