使用ngb-pagination分页时*ngFor循环index重置为0的解决方案求助
解决Angular分页后*ngFor index重置的问题
这问题我之前也碰到过!核心原因是你用slice分页后,*ngFor遍历的是原数组的子集,所以index是基于当前页的子集重新计数的,自然每次切页都会从0开始。这在你用index绑定formControlName或者checkbox id的时候就会出问题——不同页的元素会共用同一个index值,导致表单控件关联错误或者DOM元素id重复。
下面给你两种可行的解决方案:
方案一:获取元素在原数组中的真实索引
既然你的filteredAppointmentsList是完整的数据源,我们可以直接获取每个元素在原数组中的真实位置,替代*ngFor提供的子集index:
修改模板代码
<table class="table records-content-table " role="grid"> <thead> <tr role="row"> <th>Name</th> </tr> </thead> <tbody> <ng-container formArrayName="broadcastAppointment" *ngFor="let appointment of filteredAppointmentsList | slice: (page-1)*ngPageSize : (page-1)*ngPageSize + ngPageSize; trackBy:trackByAppointmentId"> <!-- 用原数组的真实索引替代子集index --> <ng-container let-originalIndex="filteredAppointmentsList.findIndex(item => item.id === appointment.id)"> <tr class="table-tr-hover"> <td (click)="fetchAppointmentMessages(appointment, originalIndex, $event, 'row')" (change)="countSelectedApptId(originalIndex, $event)" class="textEclipse" title="{{appointment.clientName}}"> <span class="multiselectAppointmentDiv ml-1 mr-1" *ngIf="allowApptToBroadcast"> <input id="selectAppt-{{originalIndex}}" name="name" (click)="fetchAppointmentMessages(appointment, originalIndex, $event)" class="broadcastChkBox apptListChkBox" type="checkbox" [formControlName]="originalIndex"> <label for="selectAppt-{{originalIndex}}" class="control-label"></label> </span> </td> </tr> </ng-container> </ng-container> </tbody> </table>
方案二:在组件中封装获取真实索引的方法
如果模板里直接写findIndex觉得不够优雅,或者数组较大担心性能,可以在组件类里封装一个方法:
组件类代码
getOriginalAppointmentIndex(appointment: any): number { // 这里用你的appointment唯一标识字段替换id return this.filteredAppointmentsList.findIndex(item => item.id === appointment.id); }
修改模板代码
<table class="table records-content-table " role="grid"> <thead> <tr role="row"> <th>Name</th> </tr> </thead> <tbody> <ng-container formArrayName="broadcastAppointment" *ngFor="let appointment of filteredAppointmentsList | slice: (page-1)*ngPageSize : (page-1)*ngPageSize + ngPageSize; trackBy:trackByAppointmentId"> <tr class="table-tr-hover"> <td (click)="fetchAppointmentMessages(appointment, getOriginalAppointmentIndex(appointment), $event, 'row')" (change)="countSelectedApptId(getOriginalAppointmentIndex(appointment), $event)" class="textEclipse" title="{{appointment.clientName}}"> <span class="multiselectAppointmentDiv ml-1 mr-1" *ngIf="allowApptToBroadcast"> <input id="selectAppt-{{getOriginalAppointmentIndex(appointment)}}" name="name" (click)="fetchAppointmentMessages(appointment, getOriginalAppointmentIndex(appointment), $event)" class="broadcastChkBox apptListChkBox" type="checkbox" [formControlName]="getOriginalAppointmentIndex(appointment)"> <label for="selectAppt-{{getOriginalAppointmentIndex(appointment)}}" class="control-label"></label> </span> </td> </tr> </ng-container> </tbody> </table>
关键说明
- 两种方案都是基于元素的唯一标识(比如你的
appointment.id)来获取真实索引,避免了分页子集的index限制。 - 你已经在使用
trackBy:trackByAppointmentId,这非常好——它能优化ngFor的渲染性能,和我们的解决方案完全兼容,不会有冲突。
内容的提问来源于stack exchange,提问作者Salman Khan
相关产品推荐
相关产品推荐

