Angular12中Mat-Icon点击全部变更问题:寻求单个图标修改方案
问题原因
你遇到的问题是因为所有星星组共享了同一个全局的rating变量——当你点击任意一个星星时,这个全局变量会被更新,所有依赖它的星星图标都会同步变化。同时HTML中的*ngIf="this.etoile=='star_'+i"逻辑错误,会导致图标无法正常显示。
解决方案
核心思路是为每个问题的每组星星分配独立的评分存储,让不同组的状态互不干扰。具体步骤如下:
1. 替换全局评分变量为分组存储
在组件类中删除全局的rating: number = 0;,改为两个对象分别存储两组星星的评分(对应你HTML中的两组按钮):
// 存储第一组星星的评分,键为问题索引(或问题ID) firstQuestionRatings: { [key: number]: number } = {}; // 存储第二组星星的评分 secondQuestionRatings: { [key: number]: number } = {};
2. 修改点击事件方法
将原来的onClick拆分为两个方法,分别处理两组星星的点击,更新对应组的评分:
// 处理第一组星星的点击 onClickFirst(rating: number, questIndex: number) { this.firstQuestionRatings[questIndex] = rating; this.snackBar.open(`第一组评分:${rating} / ${this.starCount}`, '', { duration: this.snackBarDuration }); return false; } // 处理第二组星星的点击 onClickSecond(rating: number, questIndex: number) { this.secondQuestionRatings[questIndex] = rating; this.snackBar.open(`第二组评分:${rating} / ${this.starCount}`, '', { duration: this.snackBarDuration }); return false; }
3. 修改图标显示逻辑
更新图标显示方法,让每个组根据对应存储的评分返回图标类型:
// 返回第一组星星的图标 showFirstIcon(i: number, questIndex: number) { const currentRating = this.firstQuestionRatings[questIndex] || 0; return currentRating >= i + 1 ? 'star' : 'star_border'; } // 返回第二组星星的图标 showSecondIcon(i: number, questIndex: number) { const currentRating = this.secondQuestionRatings[questIndex] || 0; return currentRating >= i + 1 ? 'star' : 'star_border'; }
4. 更新HTML模板
移除无效的*ngIf条件,为每组星星绑定对应的点击方法和图标显示方法,并传递问题索引作为标识:
<li *ngFor="let quest of Questions; let questIndex = index"> <!-- 第一组星星 --> <button mat-icon-button [color]="color" *ngFor="let ratingId of ratingArr; index as i" [id]="'star_first_' + questIndex + '_' + i" (click)="onClickFirst(i+1, questIndex)" matTooltip="{{ratingId+1}}" matTooltipPosition="above" > <mat-icon> {{ showFirstIcon(i, questIndex) }} </mat-icon> </button> <br><br> <!-- 第二组星星 --> <button mat-icon-button [color]="color" *ngFor="let ratingId of ratingArr; index as i" [id]="'star_second_' + questIndex + '_' + i" (click)="onClickSecond(i+1, questIndex)" matTooltip="{{ratingId+1}}" matTooltipPosition="above" > <mat-icon> {{ showSecondIcon(i, questIndex) }} </mat-icon> </button> </li>
修改后的完整代码
TypeScript代码
import { Component, OnInit, Input, Output, EventEmitter, ViewEncapsulation } from '@angular/core'; import { LoginService } from 'src/app/services/login.service'; import { NgxSpinnerService } from 'ngx-spinner'; import { MatDialog } from '@angular/material/dialog'; import { MatSnackBar } from '@angular/material/snack-bar'; import { FormGroup, FormControl, Validators } from '@angular/forms'; @Component({ selector: 'app-historique', templateUrl: './historique.component.html', styleUrls: ['./historique.component.css'], encapsulation: ViewEncapsulation.Emulated }) export class HistoriqueComponent implements OnInit { @Input('color') public color: string = 'accent'; @Output() public ratingUpdated = new EventEmitter(); public snackBarDuration: number = 2000; public ratingArr : number[] = []; Questions: any = []; listDeReponses: any[] = []; starCount: number = 5; etoile: string='star_border'; selectedRow :any; // 存储两组星星的独立评分 firstQuestionRatings: { [key: number]: number } = {}; secondQuestionRatings: { [key: number]: number } = {}; myForm = new FormGroup({ bouton: new FormControl('', [Validators.required]), }); constructor( private _loginService: LoginService, public spinner: NgxSpinnerService, public dialog: MatDialog, public snackBar: MatSnackBar ) { } ngOnInit(): void { for (let index = 1; index <= this.starCount; index++) { this.ratingArr.push(index); } var mat = localStorage.getItem('matricule'); var matricule1 = mat!.replace('"', ''); var matricule = matricule1.replace('"', ''); var for1 = localStorage.getItem('formation'); var form = for1!.replace('"', ''); var formation = form.replace('"', ''); this._loginService.GetQuestionsByFormation(matricule,Number(formation)).subscribe( data => { this.Questions = data; }); } onClickFirst(rating: number, questIndex: number) { this.firstQuestionRatings[questIndex] = rating; this.snackBar.open(`第一组评分:${rating} / ${this.starCount}`, '', { duration: this.snackBarDuration }); return false; } onClickSecond(rating: number, questIndex: number) { this.secondQuestionRatings[questIndex] = rating; this.snackBar.open(`第二组评分:${rating} / ${this.starCount}`, '', { duration: this.snackBarDuration }); return false; } showFirstIcon(i: number, questIndex: number) { const currentRating = this.firstQuestionRatings[questIndex] || 0; return currentRating >= i + 1 ? 'star' : 'star_border'; } showSecondIcon(i: number, questIndex: number) { const currentRating = this.secondQuestionRatings[questIndex] || 0; return currentRating >= i + 1 ? 'star' : 'star_border'; } } export enum StarRatingColor { primary = "primary", accent = "accent", warn = "warn" }
HTML代码
<li *ngFor="let quest of Questions; let questIndex = index"> <!-- 第一组星星 --> <button mat-icon-button [color]="color" *ngFor="let ratingId of ratingArr; index as i" [id]="'star_first_' + questIndex + '_' + i" (click)="onClickFirst(i+1, questIndex)" matTooltip="{{ratingId+1}}" matTooltipPosition="above" > <mat-icon> {{ showFirstIcon(i, questIndex) }} </mat-icon> </button> <br><br> <!-- 第二组星星 --> <button mat-icon-button [color]="color" *ngFor="let ratingId of ratingArr; index as i" [id]="'star_second_' + questIndex + '_' + i" (click)="onClickSecond(i+1, questIndex)" matTooltip="{{ratingId+1}}" matTooltipPosition="above" > <mat-icon> {{ showSecondIcon(i, questIndex) }} </mat-icon> </button> </li>
内容的提问来源于stack exchange,提问作者gueraini youcef
相关产品推荐
相关产品推荐

