Angular实现点击列表行时仅在该行显示Loading Spinner
解决mat-selection-list点击单行仅显示对应loading的问题
当前代码使用全局的loading$流,导致点击任意行时所有行都会显示加载状态。要实现仅目标行显示loading,需要为每个月份单独维护加载状态,具体修改如下:
1. 组件类中添加行级加载状态管理
在组件的TypeScript代码里,定义一个对象来存储每个月份的加载状态,并修改请求逻辑:
// 组件类属性,存储各月份的加载状态 loadingStates: { [month: string]: boolean } = {}; // 修改selectedDate方法 selectedDate(month: string) { // 标记当前月份为加载中 this.loadingStates[month] = true; // 示例:用RxJS处理请求,请求完成后重置状态 this.yourDataService.getMonthData(month).pipe( finalize(() => { // 无论成功失败,都关闭当前月份的加载状态 this.loadingStates[month] = false; }) ).subscribe({ next: (response) => { // 请求成功后的业务处理 }, error: (error) => { // 请求失败后的错误处理 } }); }
如果使用async/await语法,代码可调整为:
async selectedDate(month: string) { this.loadingStates[month] = true; try { const response = await this.yourDataService.getMonthData(month); // 成功处理逻辑 } catch (error) { // 错误处理逻辑 } finally { this.loadingStates[month] = false; // 若组件启用OnPush变更检测,需手动触发视图更新: // this.cdr.detectChanges(); } }
2. 修改模板绑定行级加载状态
将模板中全局的loading$ | async替换为当前行月份对应的加载状态:
<mat-selection-list #months [multiple]="false" > <mat-list-item *ngFor="let month of listOfMonths" (click)="selectedDate(month)"> <mat-card class="my-1 px-1 py-2 sm-shadow"> <div class="d-flex align-items-center justify-content-between"> <!-- 仅当前月份处于加载状态时显示spinner --> <ng-container *ngIf="loadingStates[month]" > <loading-spinner class="loading-spinner" [active]="true" [diameter]="20" [strokeWidth]="2" [colour]="'primary'" ></loading-spinner> </ng-container> <fa-icon [icon]="cIcon" class="c-icon"></fa-icon> <div class="settlement-item flex-fill mx-2 d-flex align-items-center justify-content-between"> <span class="info" data-test="date">{{ month }}</span> </div> <fa-icon [icon]="icon" class="download-icon"></fa-icon> </div> </mat-card> </mat-list-item> </mat-selection-list>
关键说明
- 用
loadingStates对象替代全局loading流,实现了行级状态隔离,每个月份的加载状态独立维护。 finalize或finally确保请求完成后必重置加载状态,避免出现永久加载的异常情况。- 若组件启用
ChangeDetectionStrategy.OnPush,需注入ChangeDetectorRef并在状态变更时手动触发视图更新。
内容的提问来源于stack exchange,提问作者Hughesey
相关产品推荐
相关产品推荐

