代码之家  ›  专栏  ›  技术社区  ›  danday74

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

  •  5
  • danday74  · 技术社区  · 7 年前

    keyvalue 通过管道迭代对象的属性,如下所示:

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

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

    How to loop over object properties with ngFor in Angular

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

    谢谢

    3 回复  |  直到 7 年前
        1
  •  201
  •   ConnorsFan    6 年前

    根据角度 documentation keyvalue 管道按项目排序 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);
    }
    

    键值 管道:

    <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
    

    此外,在模板中使用该语法两次根本不会显示项目。因此,我不建议这样做。请注意 undefined 因为comparer函数不会导致任何异常,但不会更改默认行为:项目按 价值观。

        2
  •  27
  •   V_for_Vj    6 年前
    <div *ngFor="let item of object | keyvalue: 0">
      {{item.key}} : {{item.value}}
    </div>
    

    直接写入,您将以与json中相同的顺序获得数据

    keyvalue: 0
    
        3
  •  18
  •   Majedur    6 年前

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

    keyvalue: 0
    

    最终代码:

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

    但对于angular7或更高版本,您需要放置一个空函数来保持 数据未排序。

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

    在你的 .ts 文件只是把这个空函数。

      unsorted() { }
    

    希望对你有帮助。

        4
  •  15
  •   A. D'Alfonso    6 年前

    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>
    
        5
  •  8
  •   Peter Dub    6 年前

    这和公认的答案是一样的,但它有更复杂的对象,所以它可以帮助人们如何通过自定义索引字段和使用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);
        };
    

    <div *ngFor="let x of myObject | keyvalue:indexOrderAsc">
        ...
    </div>
    
        6
  •  5
  •   ank    6 年前

    <div *ngFor="let item of object | keyvalue: 0">
      {{item.key}} : {{item.value}}
    </div>
    
        7
  •  5
  •   Michał Stochmal    4 年前

    我宁愿优先于违约 keyvalue 把它伸进我的管子里。然后我用我的烟斗代替 在我的模板中。

    import {Pipe} from '@angular/core';
    import {KeyValuePipe} from '@angular/common';
    
    const keepOrder = (a, b) => a;
    
    // This pipe uses the angular keyvalue pipe but doesn't change order.
    @Pipe({
      name: 'defaultOrderKeyvalue'
    })
    export class DefaultOrderKeyvaluePipe extends KeyValuePipe {
    
      public transform(value, compareFn = keepOrder) {
        return super.transform(value, compareFn);
      }
    
    }
    
        8
  •  2
  •   Frederik Struck-Schøning    7 年前

    对, Object array

    index 并设置 timestamp 并按

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

    管道

    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>
    
        9
  •  2
  •   Michael Dimmitt    6 年前

    制作管道以将默认设置为无序:

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

    Can I call an Angular2 pipe from a pipe?

    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,
        ...
      ]
    ...
    })
    
        10
  •  1
  •   Alasdfgxc    5 年前

    我认为这是一个更干净的解决方案。取消对需要给出正确顺序的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
      }
    

    用例

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