如何在Angular中按日期年份分组并展示事件
在Angular中实现事件按年份分组展示
1. 统一数据结构与接口
首先你的Event接口字段和后端返回的JSON字段不匹配,先修正接口确保数据一致性:
export interface Event { id: string; title: string; start_date: Date; end_date: Date; location?: string; link?: string; }
2. 完善分组逻辑
补全并优化groupByYear相关逻辑,处理日期转换、分组排序,返回可直接用于模板的Observable:
import { Observable, reduce, map } from 'rxjs'; filteredEvents!: Observable<Event[]>; // 存储分组后的事件:键为年份字符串,值为对应年份的事件数组 groupedEvents$!: Observable<{ [year: string]: Event[] }>; ngOnInit() { // 基于已获取的filteredEvents进行分组 this.groupedEvents$ = this.filteredEvents.pipe( reduce((acc, event) => { // 将后端返回的日期字符串转为Date对象 const processedEvent = { ...event, start_date: new Date(event.start_date), end_date: new Date(event.end_date) }; // 提取开始日期的年份作为分组键 const year = processedEvent.start_date.getFullYear().toString(); // 初始化年份数组并推入事件 acc[year] = acc[year] || []; acc[year].push(processedEvent); return acc; }, {} as { [year: string]: Event[] }), // 对年份进行降序排序,让最新年份的事件优先展示 map(grouped => { const sortedYears = Object.keys(grouped).sort((a, b) => parseInt(b) - parseInt(a)); return sortedYears.reduce((acc, year) => { acc[year] = grouped[year]; return acc; }, {} as { [year: string]: Event[] }); }) ); }
3. 模板实现分组展示
在组件HTML中使用async管道订阅分组数据,按年份渲染事件列表:
<div class="event-wrapper"> <ng-container *ngIf="groupedEvents$ | async as groupedEvents"> <!-- 遍历每个年份分组 --> <div *ngFor="let year of Object.keys(groupedEvents)" class="year-section"> <!-- 年份标题 --> <h2 class="year-title">{{ year }}</h2> <!-- 该年份下的事件卡片列表 --> <div class="event-list"> <div *ngFor="let event of groupedEvents[year]" class="event-card"> <h3>{{ event.title }}</h3> <p> 时间:{{ event.start_date | date:'yyyy-MM-dd HH:mm' }} 至 {{ event.end_date | date:'yyyy-MM-dd HH:mm' }} </p> <p *ngIf="event.location">地点:{{ event.location }}</p> <a *ngIf="event.link" [href]="event.link" target="_blank">查看详情</a> </div> </div> </div> </ng-container> </div>
4. 基础样式适配
添加CSS样式让分组展示更贴合预期UI:
.event-wrapper { max-width: 1200px; margin: 2rem auto; padding: 0 1rem; } .year-section { margin-bottom: 2rem; padding-bottom: 1.5rem; border-bottom: 1px solid #e0e0e0; } .year-title { color: #2d3748; font-size: 1.8rem; margin-bottom: 1rem; } .event-card { background-color: #f7fafc; padding: 1rem; border-radius: 8px; margin-bottom: 1rem; } .event-card h3 { margin-top: 0; color: #1a202c; } .event-card p { margin: 0.5rem 0; color: #4a5568; }
可选扩展
如果需要将跨年份的事件(开始和结束年份不同)同时分到两个年份组中,可修改分组逻辑:
// 替换reduce中的处理逻辑 const startYear = processedEvent.start_date.getFullYear().toString(); const endYear = processedEvent.end_date.getFullYear().toString(); // 推入开始年份组 acc[startYear] = acc[startYear] || []; acc[startYear].push(processedEvent); // 若结束年份不同,同时推入结束年份组 if (startYear !== endYear) { acc[endYear] = acc[endYear] || []; acc[endYear].push(processedEvent); }
内容的提问来源于stack exchange,提问作者user475391
相关产品推荐
相关产品推荐

