Угловой NgFor с трубными значениями keyvalue выходит из строя - PullRequest
0 голосов
/ 13 февраля 2019

Я пытаюсь сделать гексгрид.Таким образом, я извлекаю коллекцию гексов из firestore, сортирую их по id, перемещаю их в строку из 10 (так что первые 10 идут в 'row0', следующие 10 в 'row1' и т. Д.), И использую ngFor для их отображения.

Проблема в том, что когда я их отображаю, я получаю следующее:

row0

row1

row10

row11

row2

row3

row4

row5

row6

row7

row8

row9

так что я явно что-то упускаю.Я думаю, что они вышли из строя, но я console.logging строк и вижу их в порядке, как и ожидалось:

Rows [row0: Array (10), row1: Array (10), row2: Array(10), row3: Array (10), row4: Array (10),…] object

Я вижу, что порядок, по-видимому, основан на первом числе после 'row', но я не уверен, почему,Любые указатели будут с благодарностью!

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>

Обновление

Поэтому, следуя указаниям Деборы, я попытался использовать сравнение и случайно "исправил".Я сделал быструю тестовую функцию с именем 'orderByRowNum', и когда я проверил, запускается ли он, он выглядит так, как будто упорядочил список, как и ожидалось:

TS:

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

HTML:

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

Это, вероятно, ужасная реализация, и я не уверен на 100%, почему она работает, но я собираюсь опубликовать ее, потому что это, по крайней мере, похоже на прогресс.

1 Ответ

0 голосов
/ 13 февраля 2019

На первый взгляд кажется, что 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, чтобы сделать его более пригодным для повторного использования.

...