Angular keyvalue パイプを使用して、次のようにオブジェクトのプロパティを反復処理する場合:
<div *ngFor="let item of object | keyvalue">
{{item.key}}:{{item.value}}
</div>
プロパティが期待した順序で繰り返されないという問題が発生しました。そして、このコメントは、この問題を経験したのは私だけではないことを示唆しています。
AngularのngForでオブジェクトプロパティをループする方法
誰かがキーバリューパイプを使用するときに反復の順序を決定するものと、特定の反復順序を強制する方法をアドバイスできますか?私の理想的な反復順序は、プロパティが追加された順序です。
ありがとう
Angular documentation によると、keyvalue
パイプはデフォルトでkey
の順序でアイテムをソートします。比較関数を提供できますその順序を変更し、key
、value
、またはオブジェクト内のプロパティのエントリ順に従って項目を並べ替えます。
次の比較関数は、アイテムをさまざまな順序で並べ替えます。
// 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
値でソートされます。
<div *ngFor="let item of object | keyvalue: 0">
{{item.key}} : {{item.value}}
</div>
直接書き込むと、jsonと同じ順序でデータが取得されます
keyvalue: 0
使用できるオブジェクトの順序を維持するには
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>
これは受け入れられた回答と同じですが、より複雑なオブジェクトを持っているため、カスタムインデックスフィールドで並べ替えたり、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>
以下のコードを試してください:
<div *ngFor="let item of object | keyvalue: 0">
{{item.key}} : {{item.value}}
</div>
はい。デフォルトでは、キーと値のペアは昇順でデータをソートします。
ソートしないでおくには、次のように変更します。
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() { }
お役に立てば幸いです。
はい、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>
パイプを作成して、デフォルトを無秩序に設定します。
// 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,
...
]
...
})