【问题标题】:Angular NgFor with keyvalue pipe displays out of order带有键值管道的 Angular NgFor 显示乱序
【发布时间】:2019-07-06 16:36:55
【问题描述】:

我正在尝试制作一个六角网格。所以我从firestore中检索一组十六进制,按id排序,将它们移动到10行(所以前10个进入'row0',接下来的10个进入'row1'等),并使用ngFor显示它们.

问题是当我显示它们时,我得到了这个:

第0行

第1行

第 10 行

第 11 行

第2行

第3行

第4行

第5行

第6行

第7行

第8行

第9行

所以我显然遗漏了一些东西。我会认为它们有问题,但我是控制台。记录行并按预期按顺序查看它们:

行 [row0: Array(10), row1: Array(10), row2: Array(10), row3: Array(10), row4: Array(10), ...] 对象

我可以看到订单似乎基于“行”之后的第一个数字,但不知道为什么。

TS:

服务

export class FirestoreService {

  constructor(private db:AngularFirestore) { }

  getHexes(){
    let hexRows = []

    let hexes = this.db.collection('hexes', ref=> ref.orderBy('id')).valueChanges().subscribe(data => {
      data.forEach((hex, index) => {
        let rowNum = Math.floor(index / 10)

        if(hexRows[`row${rowNum}`] == undefined){
          hexRows[`row${rowNum}`] = []
        }
        hexRows[`row${rowNum}`].push(hex)
      })
      console.log('Rows', hexRows, typeof hexRows);
    })

    return hexRows
  }

组件

ngOnInit() {
    this.hexRows = this.afs.getHexes()
  }

HTML:

组件

<div *ngFor="let row of hexRows | keyvalue">
  {{row.key}}
</div>

更新

因此,在 Deborah 的带领下,我尝试使用 comparefn 并意外地“修复了它”。我做了一个名为“orderByRowNum”的快速测试函数,当我检查它是否运行时,它看起来像预期的那样对列表进行了排序:

TS:

orderByRowNum = (a,b) => {
    console.log('A', a);
    return a
  }

HTML:

<div *ngFor="let row of hexRows | keyvalue:orderByRowNum">
  {{row.key}}
</div>

这可能是一个可怕的实现,我不能 100% 确定它为什么会起作用,但我会发布它,因为它至少看起来像是进步。

【问题讨论】:

  • 看起来它们是按字母顺序排列的,而不是按数字排列的,即“0”、“1”、“10”、“11”...
  • 所以当我使用 console.log 时,它只是以某种方式为我订购了吗?
  • keyvalue 管道正在订购它们。来自文档:The output array will be ordered by keys. By default the comparator will be by Unicode point value. You can optionally pass a compareFn if your keys are complex types. (angular.io/api/common/KeyValuePipe)
  • 太棒了,感谢您清除它。如果您想将其发布为答案,我很乐意接受!
  • @gv0000,你的比较器错了,一定是(a,b)=> { return (+a.substring(3))>(+b.substring(3))}跨度>

标签: angular typescript rxjs google-cloud-firestore ngfor


【解决方案1】:

从表面上看,localeCompare 似乎会有所帮助,但对我来说它没有帮助,所以我不会简单地依赖它。

您需要应用自然排序算法对键进行排序。

试试这个。 javascript 中的自然排序算法我从这里https://snipplr.com/view/36012/javascript-natural-sort/ 获取并重构它以更好地适应打字稿规则。还应用 localeCompare 而不是原生字符串压缩器。

private orderByRowNum = (aKv: KeyValue<string, any>, bKv: KeyValue<string, any>) => {

    const rx: RegExp = /(\d+)|(\D+)/g;
    const rd: RegExp = /\d+/;

    const as: string = aKv.key;
    const bs: string = bKv.key;

    const a: RegExpMatchArray = String(as).match(rx);
    const b: RegExpMatchArray = String(bs).match(rx);

    while (a.length && b.length) {
        const a1: string = a.shift();
        const b1: string = b.shift();
        if (rd.test(a1) || rd.test(b1)){
            if (!rd.test(a1)) {
                return 1;
            }
            if (!rd.test(b1)) {
                return -1;
            }
            if (a1 !== b1) {
                return Number(a1) - Number(b1);
            }
        } else {
            if (a1 !== b1) {
                return a1.localeCompare(b1);
            }
        }
    }
    return a.length - b.length;
}

最好把它放到一些 util 类中,使其更易于重用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-02
    • 2019-04-11
    • 2017-09-09
    • 2018-02-03
    • 1970-01-01
    • 2019-04-13
    相关资源
    最近更新 更多