Angular 角度键值管道排序属性/按顺序迭代

Angular 角度键值管道排序属性/按顺序迭代,angular,angular-pipe,Angular,Angular Pipe,使用角度管道迭代对象的属性时,如下所示: {{item.key}}:{{item.value} 我遇到了一个问题,属性没有按预期的顺序迭代。这一评论表明,我不是唯一一个经历过这个问题的人: 当使用keyvalue管道时,有人能建议什么决定了迭代的顺序,以及如何强制特定的迭代顺序吗?我理想的迭代顺序是添加属性的顺序 谢谢是的,对象属性会随机迭代,因为它不会作为数组存储在内存中。但是,您可以按属性进行排序 如果要按插入位置进行迭代,则需要创建一个额外的属性,如索引,并设置时间戳,并按索引排序

使用角度管道迭代对象的属性时,如下所示:


{{item.key}}:{{item.value}
我遇到了一个问题,属性没有按预期的顺序迭代。这一评论表明,我不是唯一一个经历过这个问题的人:

当使用keyvalue管道时,有人能建议什么决定了迭代的顺序,以及如何强制特定的迭代顺序吗?我理想的迭代顺序是添加属性的顺序


谢谢

是的,
对象
属性会随机迭代,因为它不会作为
数组
存储在内存中。但是,您可以按属性进行排序

如果要按插入位置进行迭代,则需要创建一个额外的属性,如
索引
,并设置
时间戳
,并按
索引
排序

下面是可以用来控制排序和迭代的管道

烟斗

从'angular2/core'导入{Pipe,PipeTransform};
@管道({name:'values'})
导出类ValuesPipe实现PipeTransform{
变换(值:any,args?:any[]):对象[]{
let keyArr:any[]=Object.keys(值),
dataArr=[],
keyName=args[0];
keyArr.forEach((key:any)=>{
值[键][键名]=键;
数据传送推送(值[键])
});
if(args[1]){
dataArr.sort((a:Object,b:Object):number=>{
返回a[keyName]>b[keyName]?1:-1;
});
}
返回数据arr;
}
}
用法

。。。
根据角度,默认情况下,
keyvalue
管道按
key
顺序对项目进行排序。您可以提供比较器功能来更改顺序,并根据
、值、或对象中属性的输入顺序对项目进行排序

以下比较器函数按各种顺序对项目进行排序:

//保留原始属性顺序
originalOrder=(a:KeyValue,b:KeyValue):数字=>{
返回0;
}
//按属性值升序排序
ValuesOrder=(a:KeyValue,b:KeyValue):数字=>{
返回a.value.localeCompare(b.value);
}
//按属性键降序排序
keyDescOrder=(a:KeyValue,b:KeyValue):数字=>{
返回a.key>b.key-1:(b.key>a.key-1:0);
}
应用于
keyvalue
管道时:


{{item.key}}:{{item.value}
{{item.key}}:{{item.value}
{{item.key}}:{{item.value}
请参见演示


提供常量或
null
而不是有效的比较器函数会保留对象属性的输入顺序,就像
originalOrder
一样,但会导致异常(请参阅):


错误类型错误:比较函数必须是函数或未定义

此外,在模板中使用该语法两次根本不会显示项目。因此,我不建议这样做。请注意,作为比较器函数提供
未定义的
,不会导致任何异常,但不会更改默认行为:项目按
值排序。

这与公认答案相同,但它有更复杂的对象,因此它可以帮助用户如何按自定义索引字段和使用keyval管道进行排序

在角分量中:

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);
    };
组件中的排序功能:

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);
    };
indexOrderAsc=(akv:KeyValue,bkv:KeyValue):number=>{
常数a=akv.value.index;
常数b=bkv.value.index;
返回a>b1:(b>a-1:0);
};
在模板中:

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

...

要保持对象的顺序,可以使用

keepOrder = (a, b) => {
    return a;
}
假设你有

wbs = {
"z": 123,
"y": 456,
"x": 789,
"w": 0#*
}
如果使用keyvalue,则按键按字母顺序排列

w 0#*
x 789
y 456
z 123
应用:保持对象的顺序

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

{{w.key}}
{{w.value}}

试试下面的代码:

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

{{item.key}}:{{item.value}

制作一个管道,将默认设置为无序:

// 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)
  }
}
链接:

模板用法:

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

是,默认情况下,键值对按升序排序数据

要使其不排序,请修改为:

keyvalue: 0
最终代码:


希望能有所帮助。

我认为这是一种更清洁的解决方案。取消注释需要给出正确顺序的return语句:

interface KeyValue<K, V> {
  key: K,
  value: V
}

// Order by descending property key
  keyOrder = (aA: KeyValue<string,any>, bB: KeyValue<string,any>): number => {
    const a = aA.value.index;
    const b = bB.value.index;
    //return a > b ? 1 : (b > a ? -1 : 0); // ASCENDING
    return a > b ? -1 : (b > a ? 1 : 0); // DESCENDING
  }
接口键值{
关键:K,
值:V
}
//按属性键降序排序
keyOrder=(aA:KeyValue,bB:KeyValue):数字=>{
常数a=aA.value.index;
常数b=bB.value.index;
//返回a>b?1:(b>a?-1:0);//升序
返回a>b-1:(b>a-1:0);//降序
}
用例

<div *ngFor="let x of y | keyvalue: keyOrder;">
   {{ x.key  }} indexes: {{ x.value.index }}
</div>

{x.key}}索引:{x.value.index}

我更喜欢通过在管道中扩展来覆盖默认的
keyvalue
行为。然后我在模板中使用管道而不是
keyvalue

从'@angular/core'导入{Pipe};
从“@angular/common”导入{KeyValuePipe};
常数keepOrder=(a,b)=>a;
//此管道使用角度键值管道,但不更改顺序。
@烟斗({
名称:“defaultOrderKeyvalue”
})
导出类DefaultOrderKeyvaluePipe扩展了KeyValuePipe{
公共转换(值,compareFn=keepOrder){
返回super.transform(value,compareFn);
}
}

排序函数中的参数不应该是KeyValue吗?优秀的解决方案“any”解决了我的问题我在使用这个内部数据表如果我根本不想对它们进行排序怎么办?@Tenzolinho-您可以根据需要实现比较器函数。您可以尝试返回一个随机值来创建无序列表。或者总是归零。@ConnorsFan非常感谢你,你是个救命恩人。我写了
keyvalue:0
,它们是按原始顺序排列的。
keyvalue:0
在Angular 7中不再起作用。只需创建一个空函数:
sortNull(){}
an
<div *ngFor="let item of object | keyvalue: unsorted">
      {{item.key}}:{{item.value}}
    </div>
  unsorted() { }
interface KeyValue<K, V> {
  key: K,
  value: V
}

// Order by descending property key
  keyOrder = (aA: KeyValue<string,any>, bB: KeyValue<string,any>): number => {
    const a = aA.value.index;
    const b = bB.value.index;
    //return a > b ? 1 : (b > a ? -1 : 0); // ASCENDING
    return a > b ? -1 : (b > a ? 1 : 0); // DESCENDING
  }
<div *ngFor="let x of y | keyvalue: keyOrder;">
   {{ x.key  }} indexes: {{ x.value.index }}
</div>