我正在尝试根据从可观察对象获得的值对数组元素进行分组,并在视图上将这些组显示为不同的<mat-card>
。
我有一个内存网络API模块,其中包含以下简化示例的类。
我仍在学习Angular,所以请原谅我
例如: in-memory-data.service.ts
export class InMemoryDataService implements InMemoryDbService {
createDb(){
const apps = [
{id: '1', app: 'app1', env_id:2, env:'DEV'},
{id: '2', app: 'app2' env_id:2, env:'DEV'},
{id: '4', app: 'app3' env_id:2, env:'DEV'},
{id: '5', app: 'app1' env_id:3, env:'Test'},
{id: '6', app: 'app2' env_id:3, env:'Test'},
{id: '7', app: 'app3' env_id:1, env:'PROD'},
];
return {apps}
}
应该为每个不同的应用程序值创建一个新的<mat-card>
,而不是为每个应用程序值创建一个新值。
这是我的代码。
applications.service.ts 编辑:
import { Injectable } from '@angular/core';
import { Apps } from './applications';
import { APPS } from './mock-applications';
import { Observable, of } from 'rxjs';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { MessagesService } from './messages.service';
import { catchError, map, switchMap, tap, groupBy, mergeMap } from 'rxjs/operators';
export class ApplicationsService {
private applicationUrl = 'api/apps';
constructor(private messageService: MessagesService, private http: HttpClient ) { }
getApps(): Observable<Apps[]> {
return this.http.get<Apps[]>(this.applicationUrl)
.pipe(
groupBy(application=> application.app),
mergeMap(obs => {
retun obs.pipe(
toArray(),
map(apps => {
return {id: obs.key, group: apps}
})
)
}),
toArray(),
tap(_ => this.log('fetched apps')),
catchError(this.handleError<Apps[]>('getApps', []))
)
}
/*Type 'Observable<Apps[] | {}[]>' is not assignable to type 'Observable<Apps[]>'.
Type 'Apps[] | {}[]' is not assignable to type 'Apps[]'.
Type '{}[]' is not assignable to type 'Apps[]'.
Type '{}' is missing the following properties from type 'Apps': guid, mots_spi_indicator, mots_sox_indicator, mots_pci_indicator, and 42 more./*
getApp(id: string): Observable<Apps> {
const url = `${this.applicationUrl}/${id}`;
return this.http.get<Apps>(url).pipe(
tap(_ => this.log(`fetched app guid=${id}`)),
catchError(this.handleError<Apps>(`getApp guid=${id}`))
);
}
}
home.component.ts
import { Component, OnInit } from '@angular/core';
import { Apps } from '../../applications'
import { APPS } from '../../mock-applications';
import { ApplicationsService } from 'src/app/applications.service';
export class HomeComponent implements OnInit {
apps: Apps[];
constructor(private appService: ApplicationsService) { }
ngOnInit() {
this.getApps();
}
getApps(): void{
this.appService.getApps()
.subscribe(apps => this.apps = apps);
}
}
home.component.html
<h1>My Access</h1>
<app-app-search></app-app-search>
<div fxLayout="row wrap">
<div *ngFor="let app of apps" fxFlex.gt-sm="25" fxFlex.gt-xs="50" fxFlex="100">
<a routerLink="/detail/{{app.id}}">
<mat-card class="card-widget mat-teal">
<div mat-card-widget>
<div mat-card-float-icon>
<mat-icon>error</mat-icon>
</div>
<div class="pl-0">
<h2 mat-card-widget-title>{{app.app}}</h2>
</div>
</div>
</mat-card>
</a>
</div>
</div>
如何做到这一点,以便将每个应用程序名称都放在自己的组中?
答案 0 :(得分:2)
这是一种分组方式:
export class AppComponent implements OnInit {
apps$: Observable<any>;
createDb() {
const apps = [
{ id: '1', app: 'app1', env_id: 2, env: 'DEV' },
{ id: '2', app: 'app2', env_id: 2, env: 'DEV' },
{ id: '4', app: 'app3', env_id: 2, env: 'DEV' },
{ id: '5', app: 'app1', env_id: 3, env: 'Test' },
{ id: '6', app: 'app2', env_id: 3, env: 'Test' },
{ id: '7', app: 'app3', env_id: 1, env: 'PROD' },
];
return from(apps)
}
ngOnInit() {
this.apps$ = this.createDb().pipe(
// Tell rx which property to group by
groupBy(application => application.app),
mergeMap(obs => {
// groupBy returns a GroupedObservable, so we need to expand that out
return obs.pipe(
toArray(),
map(apps => {
return {id: obs.key, group: apps}
})
)
}),
toArray(),
)
}
}
<div *ngFor="let app of apps$ | async">
<h4>{{ app.id }}</h4>
<ul>
<li *ngFor="let item of app.group">{{ item | json }}</li>
</ul>
</div>
输出:
app1
{ "id": "1", "app": "app1", "env_id": 2, "env": "DEV" }
{ "id": "5", "app": "app1", "env_id": 3, "env": "Test" }
app2
{ "id": "2", "app": "app2", "env_id": 2, "env": "DEV" }
{ "id": "6", "app": "app2", "env_id": 3, "env": "Test" }
app3
{ "id": "4", "app": "app3", "env_id": 2, "env": "DEV" }
{ "id": "7", "app": "app3", "env_id": 1, "env": "PROD" }
答案 1 :(得分:0)
为此使用lodash
npm install lodash
import * as groupBy from "lodash/groupBy";
...
getApps(): void{
this.appService.getApps()
.subscribe(apps => {
var grouppedApps = groupBy(apps,"app");
// You can do whatever you want now
} );
}
答案 2 :(得分:0)
from()
运算符创建一个可观测值f ires the elements of the array and then terminates。 toArray()
运算符collects all source emissions and emits them as an array when the source completes.因此,对于您没有要发射的一组固定值的用例,不能使用toArray()
。但是,您可以将map
与lodash中的_.groupBy()
一起使用。这是我针对这种特殊情况所做的:
this.filteredMeetingList$ = this.sorting$.pipe(
switchMap(sorting => this.meetingList$.pipe(
// ...
map(sMeetings => sMeetings.map(m => ({
...m,
day: moment(m.startDateTime).format('DD. MMM'),
}))),
)),
map(elem => _.groupBy(elem, 'day')),
);