如何重新排序ngFor组件中的项目? Angular 2+

问题描述 投票:1回答:2

我对Angular相当新,所以这可能是一个简单的修复。

目前,我使用API​​调用了3张不同的卡。然后我使用* ngFor循环这些项目并为每个项目创建一张卡片,如下所示:

<div *ngFor="let exploreCard of exploreCards" class="col-sm">
                    <div class="card three-col">
                        <img class="card-img-top" [src]="exploreCard.ImageUrl" alt="Card image cap" />
                        <div class="card-body">
                            <h5 class="card-title">{{exploreCard.Title}}</h5>
                            <p class="card-text">{{exploreCard.Description}}</p>
                            <p>{{exploreCard.Sequence}}</p>
                        </div>
                   </div>
 </div>

你会看到我有一个打印出来的序列号。现在我的json正坐在这里,当API检索它时,它以3 , 2 , 1的顺序返回。

我想以1 , 2 , 3的顺序返回它。但是我知道我可以使用管道,但我需要它尽可能快地运行。我也不想只是颠倒返回项目的顺序,因为这对于将来的添加是不可持续的。

这是我的组件中的代码,它在初始化时运行:

this.exploreService.getExploreCards()
            .subscribe(z => {
                this.exploreCards = z;
                if (this.exploreCards != null && this.exploreCards.length > 0) {
                    this.showLoader = false;
                }
            })

exploreCards看起来像这样:

private exploreCards: ExploreCard[];

有谁知道如何通过组件中的逻辑实现正确的排序?

提前致谢。

编辑:

这是我的getExploreCards()方法:

public getExploreCards(): BehaviorSubject<ExploreCard[]> {
        if (this.exploreCards === null) {
            this.exploreCards = new BehaviorSubject<ExploreCard[]>(null);
            this.http.get(`${this.baseUrl}api/Explore/GetExploreCards`).pipe( 
                retry(3) 
            )
                .subscribe((x: ExploreCard[]) => this.exploreCards.next(x));

        }
        return this.exploreCards;
    }
angular sorting
2个回答
1
投票

您可以在从服务中检索卡片时对卡片进行排序:

this.exploreService.getExploreCards()
            .subscribe(z => {
                if(z != null) {
                    this.exploreCards = z.sort((a,b) => a.Sequence - b.Sequence);
                }
            })

或者当卡片应该总是排序时,我会把排序放在服务中。

或者你可以写排序管道;)

您也可以使用一些实用功能而不是本机javascript,例如。从lodash到按属性排序:

_.sortBy(cards, card => card.Sequence );

顺便说一句。你不应该在订阅中设置this.showLoader = false;,而是在finally操作符中设置,这样当你的服务调用失败时你的加载器就不再可见了。


0
投票

您不应该在组件中执行此操作,而是使用getExploreCards()方法:

getExploreCards(): Observable<ExploreCard[]> {
  this.http.get('link/to/cards').pipe(
    tap((cards) => cards.sort((a, b) => a.Sequence - b.Sequence))
  )
}

另外,考虑使用async管道,这将消除必须取消订阅组件的必要性。否则你将挂起订阅,并随之发生内存泄漏。例如,这将是你的html然后:

<div *ngIf="!(exploreCards$ | async)" class="loader"></div>

<div *ngFor="let exploreCard of exploreCards$ | async" class="col-sm">
 <!-- the rest -->
</div>

你的ts将是这样的:

readonly exploreCards$: Observable<ExploreCard[]> = this.exploreService.getExploreCards();

但这完全取决于你:)

- 编辑 -

要更新您的方法并使逻辑更简单,可以使用rxjs中的shareReplay()运算符:

private exploreCards = this.http.get(`${this.baseUrl}api/Explore/GetExploreCards`).pipe( 
  retry(3),
  tap((cards) => cards.sort((a, b) => a.Sequence - b.Sequence)),
  shareReplay() 
)

public getExploreCards(): Observable<ExploreCard[]> {
  return this.exploreCards;
}

如果你坚持使用BehaviourSubject,你可以使用:

public getExploreCards(): BehaviorSubject<ExploreCard[]> {
  if (this.exploreCards === null) {
    this.exploreCards = new BehaviorSubject<ExploreCard[]>(null);
    this.http.get(`${this.baseUrl}api/Explore/GetExploreCards`).pipe( 
      retry(3),
      tap((cards) => cards.sort((a, b) => a.Sequence - b.Sequence)) 
    ).subscribe((x: ExploreCard[]) => this.exploreCards.next(x));
  }

  return this.exploreCards;
}

但请注意,这是非常“反模式”,并为挂起订阅留出空间。仅仅因为你的团队使用它,并不意味着它是正确的方式;)只是我的2c。

© www.soinside.com 2019 - 2024. All rights reserved.