如何以嵌套方式呈现记录列表 Angular 异步管道

How to render a list of records in a nested manner Angular async pipe

如何在Angular中以嵌套方式呈现单个记录列表?我有一系列约会记录。我想按天对约会进行分组。如果您在 Javascript 中使用嵌套循环生成 HTML 自己,这很简单,但我不知道如何在 Angular *ngFor 中从单个列表(嵌套 *ngFors有多个列表很容易)。

这是问题的简化版本。一、数据模型

export interface Appointment {
    scheduled: Date;
    client: string;
}
  appointments$: Observable<Appointment[]>;

这是我想要呈现的方式,按天分组,然后是每天下方的客户名称列表。

然后最后是 HTML 来生成那张图片。

 <ion-item-group>
    <ion-item-divider>
      <ion-label>MON 15</ion-label>
    </ion-item-divider>
  
    <ion-item>
      <ion-label>Alfred Futter</ion-label>
    </ion-item>
    <ion-item>
      <ion-label>Around the Trumpet</ion-label>
    </ion-item>
  </ion-item-group>
  
  <ion-item-group>
    <ion-item-divider>
      <ion-label>TUE 16</ion-label>
    </ion-item-divider>
    <ion-item>
      <ion-label>Antonio Taco</ion-label>
    </ion-item>
    <ion-item>
      <ion-label>Berglunds</ion-label>
    </ion-item>
    <ion-item>
      <ion-label>Blondel and Sons</ion-label>
    </ion-item>
  </ion-item-group>

所以现在的问题是我有一组约会,通常在 Angular 中迭代,如下所示:

<ion-item-group *ngFor="let appt of appointments$ | async">
...
<ion-item-group>

但这只是生成离子项组的外部列表。我还如何使用 appts.scheduled 字段分组来生成每天的 ion-items 内部子组?

谢谢。

编辑:根据下面@E.Maggini 的要求,我自己的解决方案。首先,我修改了服务本身以按天对约会进行分组,如下所示:

    appointments = Object.values(_.groupBy(appointments, a => a.scheduled.getDate()));

(是的,我知道仅仅 getDate() 是不够的,这只是为了概念验证)

然后下面的 HTML 足以完全按照需要渲染它:

  <ion-list>
    <ion-item-group *ngFor="let apptsOneDay of appointments$ | async">
      <ion-item-divider>
        <ion-label>{{apptsOneDay[0].scheduled}}</ion-label>
      </ion-item-divider>
      <ion-item *ngFor="let appt of apptsOneDay">
        <ion-label>{{appt.name}}</ion-label>
      </ion-item>
    </ion-item-group>    
  </ion-list>  

我更愿意根据@GaurangDhorda 的建议使用 RXJS 运算符对服务返回的 Observable 进行操作,但我无法让运算符链工作。

在此 Stackblitz Link

中完成工作演示

基本上,您需要做的就是使用 groupBy、mergeMap 和 toArray rxjs 运算符通过管道传输您的约会可观察对象,以便您获得 groupBy 日期数据,并且您可以将此数据用于模板并使用嵌套的 ngFor 进行遍历。这是您的可观察管道代码..

appointment$: Observable<appointmentObservable[]> = of(
this.appointmentData).pipe(
   mergeMap((parentData) => parentData),
   groupBy((parentGroup) => parentGroup.scheduled.toLocaleDateString()),
   mergeMap((group) => this.reducePipe(group)),
   toArray()
);

reducePipe(group: GroupedObservable<string, appointment>) {
  return group.pipe(
    reduce(
      (acc, cur) => {
        acc.clients.push(cur);
          return acc;
        },
        { scheduled: new Date(group.key), clients: [] }
      )
     );
 }

在上面的代码中,groupBy 运算符的这一行 parentGroup.scheduled.toLocaleDateString() 正在获取计划日期类型的数据,我们将其转换为 localString 并将其传递给下一个 mergeMap 管道。然后我们使用 reduce 运算符,再次使用 scheduled: new Date(group.key) 这一行将 stringDate 转换为 dateFormat 日期。

现在 HTML 是...

<ng-container *ngIf="appointment$ | async as appointments">
   <ion-item-group *ngFor="let appointment of appointments">
      <ion-item-divider>
         <ion-label>{{ appointment.scheduled | date: 'EEE dd' }}</ion-label>
      </ion-item-divider>
      <ion-item *ngFor="let userNames of appointment.clients">
         <ion-label>{{ userNames.client }}</ion-label>
      </ion-item>
   </ion-item-group>
</ng-container>

在上面 html 中,我们使用 angular 的 appointment.scheduled | date: 'EEE dd' 日期管道,其格式可将日期转换为您需要的格式,例如 MON 21。谢谢。