Angular中如何用async管道嵌套渲染按天分组的预约记录列表
Angular 预约列表按天分组渲染解决方案
核心思路
不需要修改后端服务返回结构,直接通过RxJS操作符对原始Observable<Appointment[]>做流式转换,生成按天分组的二维数组,再配合双层*ngFor实现渲染。
具体实现步骤
1. 组件类中转换数据流
首先导入RxJS的map操作符,对原始预约数据流做分组处理:
import { map } from 'rxjs'; // 如果使用lodash的groupBy可以直接导入,也可以自己实现分组逻辑避免第三方依赖 import groupBy from 'lodash/groupBy'; export class YourComponent { // 原始服务返回的预约流 appointments$: Observable<Appointment[]> = this.yourService.getAppointments(); // 转换后的按天分组预约流 groupedAppointments$ = this.appointments$.pipe( map(appointments => { // 按完整年月日分组,避免不同月/年的同天数据被错误合并 const groupedByDay = groupBy(appointments, appt => { const date = appt.scheduled; return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`; }); // 可选:按日期升序排序分组 const sortedGroups = Object.entries(groupedByDay) .sort(([dateA], [dateB]) => new Date(dateA).getTime() - new Date(dateB).getTime()) .map(([_, appointments]) => appointments); return sortedGroups; }) ); }
如果不想引入lodash依赖,可以用原生JS实现分组逻辑:
const groupedByDay = appointments.reduce((groups, appt) => { const dateKey = `${appt.scheduled.getFullYear()}-${appt.scheduled.getMonth() + 1}-${appt.scheduled.getDate()}`; if (!groups[dateKey]) groups[dateKey] = []; groups[dateKey].push(appt); return groups; }, {} as Record<string, Appointment[]>);
2. 模板渲染
配合Angular自带的DatePipe格式化日期头,直接使用双层*ngFor渲染即可:
<ion-list> <ion-item-group *ngFor="let dayAppointments of groupedAppointments$ | async"> <ion-item-divider> <!-- 格式化日期为 周几+日期 格式,比如 MON 15 --> <ion-label>{{ dayAppointments[0].scheduled | date:'EEE d' | uppercase }}</ion-label> </ion-item-divider> <ion-item *ngFor="let appt of dayAppointments"> <ion-label>{{ appt.client }}</ion-label> </ion-item> </ion-item-group> </ion-list>
注意:你的原模板中写的appt.name是笔误,按照定义的接口应该取appt.client字段
优化建议
- 可以添加空状态判断,当某天没有预约时不渲染对应分组头
- 如果数据量很大,可以搭配
trackBy优化*ngFor的渲染性能 - 时间敏感的场景可以加上时区处理,避免跨时区用户显示日期错误
内容的提问来源于stack exchange,提问作者royappa
相关产品推荐
相关产品推荐

