我有一个来自firebase的列表,我想要过滤和显示每个类别下的专业化知识。当我执行控制台日志时,将同时检索类别和专业,但是当选择类别时,我无法弄清楚在UI中呈现专业化所需做的事情。任何指导将不胜感激。谢谢。以下是我的工作:
category.JSON
{ “ -Lq2PAU_P-fPniAMrQ85”:{ “名称”:“测试” }, “会计与金融” : { “名称”:“会计与财务” }, “ assuranceAudit”:{ “名称”:“保证和审计” }, “风险管理” : { “ name”:“风险管理” }, “税收”:{ “名称”:“税收” } }
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>
Service.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();
}
目前,我没有任何错误,但选择类别时控制台中的空数组除外。
答案 0 :(得分: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的下拉列表,并且当用户选择新值时,该select将触发一种方法来更新selectedCategory(通过在其上调用next
)。我再次在这里将值硬编码,因为这不是您提出问题的主旨。
然后通过rxjs mergeMap
运算符进行过滤。它采用selectedCategory$
可观测值发出的最新值,并将其传递给map
运算符,该运算符通过Firebase的pipe
可观测值进行categories$
。映射后的过滤类别以组件的categories$
可见的形式返回。
更新
仅参考关于初始问题的一些评论。我创建了一个非常小巧的StackBlitz,展示了使用不纯管道方法的一些低效率。如果在预览窗格中打开控制台,则可以看到调用不纯管道的次数,甚至与完全不相关的动作有关。每次调用它时,UI都会重新呈现。