我对Angular还是很陌生,所以这可能是一个简单的解决方法。
目前,我有3种不同的卡被API调用。然后,我使用* 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;
}
答案 0 :(得分: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
运算符中设置,这样,当服务调用失败时,加载程序就不再可见。
答案 1 :(得分: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>
您的问题就是这样:
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。