【问题标题】:Filter a List By Category - Angular 8按类别过滤列表 - Angular 8
【发布时间】:2019-10-08 04:50:12
【问题描述】:

我有一个来自 firebase 的列表,我想过滤并显示每个类别下的专业。 When I do console log both the categories and specializations are retrieved, but I can’t figure out what I need to be doing to render specialization in UI when category is selected.任何指导将不胜感激。谢谢。以下是我的作品:

类别.JSON

{ “-Lq2PAU_P-fPniAMrQ85”:{ “名称”:“测试” }, “会计与金融” : { “名称”:“会计与财务” }, “保证审计”:{ “名称”:“鉴证与审计” }, “风险管理” : { “名称”:“风险管理” }, “税收”:{ “名称”:“税收” } }

categories.JSON

{
  "accountingFinance" : [ null, "Accounting Management Information Systems", "Accounting Records Maintenance", "Accounts Preparation", "Accountancy / Finance Training" ],
  "assuranceAudit" : [ null, "Asset Management Review", "Assurance / Audit Training", "Climate Change / Sustainability Audit", "Enviromental Audit" ],
  "riskManagement" : [ null, "Acturial Service", "Enterprise Risk Management", "Fraud Risk Management", "Political Risk Management" ],
  "taxation" : [ null, "Business Income Tax", "Capital Gains Tax", "Corporation Tax", "Employee Tax (PAYE)", "Export Incentives" ]
}

HTML 标记

<div class="row">
                            <div class="col-4">
                                <div class="list-group">
                                    <a 
                                        *ngFor="let c of (category$ | async)" 
                                        routerLink="/admin/expert-category" [queryParams]="{ category: c.key }"
                                        class="list-group-item list-group-item-action"
                                        [class.active]="category === c.key">
                                        {{ c.name }}
                                    </a>
                                </div>
                            </div>
                            <div class="col">
                                <div class="row">
                                    <ng-container *ngFor="let categories of filteredCategories; let i = index">
                                        <div class="col">
                                            <div class="card">
                                                <!--<div class="card-body">-->
                                                    <ul class="list-group list-group-horizontal">
                                                        <li class="list-group-item">{{ categories }}</li>
                                                    </ul>
                                                <!--/div>-->
                                            </div>
                                        </div>
                                        <div  *ngIf="(i+1) % 4 === 0" class="-w-100"></div>
                                    </ng-container>     
                                </div>
                            </div>
                        </div>

服务.ts

getCategories(): Observable<any[]> {
    return this.db.list('/categories')
    .snapshotChanges().pipe(
      map(actions =>
        actions.map(data => ({ key: data.key, ...data.payload.val() }))
    ));
  }

  getAll(): Observable<any[]> {
    return this.db.list('/category')
    .snapshotChanges().pipe(
      map(category =>
        category.map(cat => {
            const key = cat.key;
            const payload = cat.payload.val();
            return { key, ...payload };
          })),
        );
  }

Component.ts 文件

export class ExpertCategoryComponent implements OnInit {
  category$;
  category: string;
  closeResult: string;
  filteredCategories: any[] = [];
  specialization: any[] = [];

  constructor(
    private categoryService: CategoryService,
    route: ActivatedRoute,
    private router: Router,
    private modalService: NgbModal) {

      this.categoryService.getCategories().subscribe(specialization => {
        this.specialization = specialization;
        console.log(this.specialization);
        route.queryParamMap.subscribe(params => {
          this.category = params.get('category');

          this.filteredCategories = (this.category) ? this.specialization.filter(s => s.category === this.category) : this.specialization;
          console.log(this.filteredCategories);
          });
      });

      this.category$ = this.categoryService.getAll();
  }

当我选择一个类别时,除了控制台中的一个空数组之外,我目前没有收到任何错误。

【问题讨论】:

标签: angular rxjs


【解决方案1】:

我用代码创建了一个StackBlitz

您在上面提供的 html 有一些小的修改。还有一个“firebase”模拟,因此您可以看到我也在使用您在上面提供的数据。您可能希望在此处查看完整示例。

此外,下面使用的许多方法都来自出色的演讲者,例如 Deborah Kurata 和其他人。

关于您关于过滤的问题,

import { Component } from '@angular/core';
import { FirebaseStub } from './firebase.stub';
import { Observable, BehaviorSubject, Subject } from 'rxjs';
import { mergeMap, map, tap } from 'rxjs/operators';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';
  private selectedCategory = new BehaviorSubject<string>('accountingFinance');

  category$: Observable<any>;
  selectedCategory$ = this.selectedCategory.asObservable();
  categories$: Observable<any>;


  constructor(private firebaseStub: FirebaseStub) {
    this.categories$ = this.selectedCategory$
                           .pipe(
                             mergeMap(selectedCategory => this.firebaseStub
                                                              .categories$
                                                              .pipe(map((category: any) => category[selectedCategory]))
                            )
                          );

    this.category$ = firebaseStub.category$
                                 .pipe(
                                   tap((category: any) => this.selectedCategory.next('accountingFinance')),
                                   map(categoryObj => Object.keys(categoryObj).map((key,index) => categoryObj[key].name))
                                  );
  }
}

我试图保持您的命名约定,尽管它们对我来说有点难以遵循。您将看到categories$ 是根据从“firebase”和selectedCategory 收到的完整列表过滤的类别列表。一般来说,我看到 selectedCategory 值来自 UI 中的下拉列表,当用户选择一个新值时,该选择会触发更新 selectedCategory 的方法(通过调用 next )。我在这里再次硬编码了一个值,因为这不是您问题的主要内容。

然后通过 rxjs mergeMap 运算符完成过滤。它通过 Firebase 的 categories$ observable 将 selectedCategory$ observable 发出的最新值传递给 map 运算符 piped。映射的过滤类别作为组件的categories$ observable 返回。

更新

仅参考最初问题上的一些 cmets。我创建了一个非常小/快速的StackBlitz,展示了使用不纯管道方法的一些低效率。如果您在预览窗格中打开控制台,您可以看到不纯管道被调用了多少次,甚至与完全不相关的操作相关。每次调用时,都会重新渲染 ui。

【讨论】:

    猜你喜欢
    • 2015-07-12
    • 2021-05-18
    • 2021-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    • 2020-04-02
    相关资源
    最近更新 更多