* ngДля заказа по наблюдаемому списку по вычисляемому свойству - PullRequest
0 голосов
/ 05 февраля 2019

Прежде всего, я француз, поэтому приношу свои извинения за мой английский ...

Я бы хотел заказать Observable с * ngFor.

Вот мой код:

this.allBoulangeries$ = this.allBoulangeriesService.getAllBoulangeries();

Я получаю все данные из базы данных.

Далее я делаю * ngFor для отображения:

<ion-card *ngFor="let boulangerie of allBoulangeries$ | async"  tappable (click)="viewDetails(boulangerie)">
        <div padding>
          <b>{{ boulangerie.name }}</b>
          <p>{{ boulangerie.address }}<br>
            {{ boulangerie.cp }} {{ boulangerie.ville }}</p>
          <p>Distance: {{ distanceTo(boulangerie.coordX, boulangerie.coordY, latitude, longitude) }}</p>
        </div>
      </ion-card>

Моя проблема в том, что я хочу заказать списоксо значением расстояния (рассчитайте по координатам и координатам с помощью функции) ... На данный момент список отображается в алфавитном порядке.

Большое спасибо за поддержку!

Ответы [ 3 ]

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

Код, который вы написали, чрезвычайно дорог с точки зрения производительности, поскольку вы вызываете функцию с синтаксисом интерполяции строк ({{}})

Я бы порекомендовал вам сделать этов самом компоненте.Попробуйте:

this.allBoulangeries$ = this.allBoulangeriesService.getAllBoulangeries()
  .pipe(
    map(boulangeries => boulangeries.map(boulangerie => {
      return { 
        ...boulangerie, 
        distance: this.distanceTo(boulangerie.coordX, boulangerie.coordY, this.latitude, this.longitude) 
      };
    })),
    map(boulangeries => boulangeries.sort((b1, b2) => b1.distance - b2.distance ))
  );
0 голосов
/ 05 февраля 2019

Решение 1: Предполагая, что у вас есть доступ к long и lat, когда вы перемещаете эти объекты в базу FireBase

Когда вы нажимаете boulangerie в Firebase, добавляете вычисленное расстояние до объектапрежде чем отправить его в базу данных.Это более эффективно, чем делать это для каждого объекта, когда вы получаете коллекцию boulangeries.

Когда вы запрашиваете коллекцию boulangeries, используйте orderBy('distance') при обращении к базе данных (при условии, что ваша база данных firebaseЗависимость называется db):

Если при использовании базы данных реального времени метод в вашем BoulangerieService будет выглядеть так:


getAll(): Observable<Boulangerie[]> {
    db.collection('items', ref => ref.orderBy('distance')).valueChanges();
}

В Firestore это будет выглядеть так:


getAll(): Observable<Boulangerie[]> {
    this.db.list('/boulangeries', ref => ref.orderByChild('distance')).valueChanges()
}

Тогда, если вам нужно отсортировать по алфавиту или по любому другому свойству, вы можете адаптировать один из каналов, представленных в других ответах, чтобы сделать это довольно красиво:)

Решение2: Если у вас нет доступа к long и lat при нажатии на firebase

Я настоятельно рекомендую вам делать следующее в сервисе, а не в компоненте - это лучше, потому что выотделяют манипулирование данными от представления их в компоненте.Это также лучший способ сделать это с помощью RxJS.Обратите внимание, что вам нужно будет импортировать оператор map из RxJS, чтобы сделать следующее:

Убедитесь, что доступны долгота и широта и ваша функция distanceTo() в службе или компоненте, где вы выполняетепозвоните в firebase и попробуйте:


// If using firestore:

getAll(): Observable<Boulangerie[]> {
    this.db.list('/boulangeries', ref => ref.orderByChild('distance')).valueChanges()
    .pipe(
        map((boulangeries: Boulangerie[]) => {
            boulanderies.forEach((boulangerie) => {
                boulangerie.distance = distanceTo(boulangerie.coordX, boulangerie.coordY, latitude, longitude)
            })
        })
    )
}

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

Вы можете создать пользовательскую трубу для расчета и упорядочения по расстоянию:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({name: 'orderByDistance'})
export class OrderByDistancePipe implements PipeTransform {
  transform(boulangeries: Boulangerie[], latitude: number, longitude: number): Boulangerie[] {
    return boulangeries.sort((a, b) => {
        return distanceTo(b.coordX, b.coordY, latitude, longitude) -
               distanceTo(a.coordX, a.coordY, latitude, longitude);
    });
  }
}

Эта труба возвращает ваш упорядоченный список буландж.Затем вы можете использовать его в своем массиве, передав массив перед конвейером и передав аргументы широты и долготы после :.

<ion-card *ngFor="let boulangerie of ((allBoulangeries$ | async) | orderByDistance:latitude:longitude)"  tappable (click)="viewDetails(boulangerie)">
    <div padding>
        <b>{{ boulangerie.name }}</b>
        <p>{{ boulangerie.address }}<br>
           {{ boulangerie.cp }} {{ boulangerie.ville }}</p>
        <p>Distance: {{ distanceTo(boulangerie.coordX, boulangerie.coordY, latitude, longitude) }}</p>
    </div>
</ion-card>

Еще один способ сделать это - отсортировать массив в компоненте., отправив по трубопроводу в вашу наблюдаемую информацию, чтобы вернуть наблюдаемую из вашего упорядоченного массива:

this.boulangeriesOrdered$ = this.boulangeries.pipe(
    map(arr => arr.sort((a, b) =>
        distanceTo(b.coordX, b.coordY, latitude, longitude) -
        distanceTo(a.coordX, a.coordY, latitude, longitude)
    ))
);

Затем вы можете использовать эту наблюдаемую информацию вместо булланов. $ 1013 *

В отношении производительности оба подхода будутсравнимо, так как порядок будет происходить каждый раз, когда наблюдаемый будет генерировать новый массив.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...