如何在不使用ngFor索引的情况下为排序后的div行设置交替颜色
解决Angular ngFor过滤后行交替颜色问题
问题核心:直接使用原始数组的index会因为过滤逻辑(按年份筛选)导致展示的行索引不连续,无法实现正确的交替颜色。
方案1:组件内预处理分组数据(推荐,性能更优)
在组件中提前将数据按年份分组并过滤,模板直接遍历处理后的分组数据,此时ngFor的index就是当前年份下展示行的连续序号。
1.1 组件逻辑修改
// 在组件类中添加属性和初始化逻辑 groupedActivities: { year: string; activities: any[] }[] = []; ngOnInit(): void { // 基于已有activityYears和activityData生成分组数据 this.groupedActivities = this.activityYears.map(year => ({ year, activities: this.activityData.filter(activity => activity.activityYear === year) })); }
1.2 模板修改
<div *ngFor="let group of groupedActivities"> <div class="bold">{{group.year}}</div> <!-- 遍历当前年份下的过滤后数据,使用i作为连续索引 --> <div *ngFor="let activity of group.activities; let i = index"> <div fxLayout="row" fxLayoutAlign="space-between center" fxLayoutGap="10px" [ngClass]="{'even-row': i % 2 === 0, 'odd-row': i % 2 !== 0}"> <div fxLayout="row wrap" fxLayoutAlign="start start" fxLayoutGap="10px"> <div class="width-80px" [ngStyle]="{'color':seasonColour(activity.activitySeason)}">{{activity.activitySeason}}</div> <div class="width-200px bold" [ngStyle]="{'color':roleColour(activity.character)}">{{activity.character}}</div> <ng-container *ngIf="!isEditing"> <div [ngStyle]="{'color':covenantServiceColour(activity.covenantService)}">{{activity.activity}}</div> </ng-container> <ng-container *ngIf="isEditing && idEdit === activity.activityID"> <div [ngStyle]="{'color':covenantServiceColour(activity.covenantService)}" class="width-500px"> <mat-form-field appearance="outline" class="fill-container"> <mat-label>Activity</mat-label> <input matInput type="text" [(ngModel)]="activityEdit" [ngModelOptions]="{standalone: true}"> </mat-form-field> </div> </ng-container> <ng-container *ngIf="isEditing && idEdit === activity.activityID"> <div> <mat-checkbox [checked]="activity.covenantService" #covServCheckbox (change)="covServiceSelect($event, activity.activityID, activity.activityYear, activity.activitySeason, activity.activitySeasonID, activity.character, activity.activity, activity.characterRole)"> Covenant Service </mat-checkbox> </div> </ng-container> </div> </div> </div> </div>
1.3 添加CSS样式
.even-row { background-color: #f5f5f5; } .odd-row { background-color: #ffffff; }
方案2:使用自定义过滤管道
如果不想修改组件逻辑,可以创建一个过滤管道,在模板中直接过滤数据,此时ngFor的index也是过滤后的连续序号。
2.1 创建过滤管道
import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'filterByYear' }) export class FilterByYearPipe implements PipeTransform { transform(activities: any[], targetYear: string): any[] { return activities.filter(activity => activity.activityYear === targetYear); } }
记得在对应模块中声明这个管道。
2.2 模板修改
<div *ngFor="let year of activityYears"> <div class="bold">{{year}}</div> <!-- 使用管道过滤后,i为当前年份下的连续索引 --> <div *ngFor="let activity of activityData | filterByYear: year; let i = index"> <div fxLayout="row" fxLayoutAlign="space-between center" fxLayoutGap="10px" [ngClass]="{'even-row': i % 2 === 0, 'odd-row': i % 2 !== 0}"> <!-- 内部内容与原代码一致 --> <div fxLayout="row wrap" fxLayoutAlign="start start" fxLayoutGap="10px"> <div class="width-80px" [ngStyle]="{'color':seasonColour(activity.activitySeason)}">{{activity.activitySeason}}</div> <div class="width-200px bold" [ngStyle]="{'color':roleColour(activity.character)}">{{activity.character}}</div> <ng-container *ngIf="!isEditing"> <div [ngStyle]="{'color':covenantServiceColour(activity.covenantService)}">{{activity.activity}}</div> </ng-container> <ng-container *ngIf="isEditing && idEdit === activity.activityID"> <div [ngStyle]="{'color':covenantServiceColour(activity.covenantService)}" class="width-500px"> <mat-form-field appearance="outline" class="fill-container"> <mat-label>Activity</mat-label> <input matInput type="text" [(ngModel)]="activityEdit" [ngModelOptions]="{standalone: true}"> </mat-form-field> </div> </ng-container> <ng-container *ngIf="isEditing && idEdit === activity.activityID"> <div> <mat-checkbox [checked]="activity.covenantService" #covServCheckbox (change)="covServiceSelect($event, activity.activityID, activity.activityYear, activity.activitySeason, activity.activitySeasonID, activity.character, activity.activity, activity.characterRole)"> Covenant Service </mat-checkbox> </div> </ng-container> </div> </div> </div> </div>
注意:管道会在每次变更检测时执行,若数据量较大,推荐使用方案1的预处理方式以避免性能损耗。
内容的提问来源于stack exchange,提问作者Dusk Childer
相关产品推荐
相关产品推荐

