Angular中mat-checkbox选中时Array.push仅存最后一项的问题修复请求
问题原因
每个<app-item>都是独立的组件实例,各自维护自己的ArrayChecked数组。选中复选框时,只是往当前item组件的数组里添加内容,其他item组件的数组不会同步,所以日志里只会显示当前item的那一项。
修复方案
把选中项的管理逻辑提升到父组件ItemListComponent,子组件只负责传递选中状态的变化,由父组件统一维护所有选中项的数组。
1. 修改子组件 item.component.ts
移除子组件内的ArrayChecked,添加@Output事件发射器,向父组件传递选中/取消选中的任务信息:
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; @Component({ selector: 'app-item', templateUrl: './item.component.html', styleUrls: ['./item.component.scss'], }) export class ItemComponent implements OnInit { @Input() value: any; @Input() isChecked: boolean; // 由父组件控制选中状态 @Output() checkChange = new EventEmitter<{ task: string; checked: boolean }>(); constructor() { this.isChecked = false; } ngOnInit(): void {} onChange($event: any) { this.checkChange.emit({ task: this.value.task, checked: $event.checked }); } }
2. 修改子组件模板 item.component.html
把[(ngModel)]绑定改成从父组件传入的isChecked,避免子组件自己维护状态:
<div class="listContainer"> <div class="checkContainer"> <mat-checkbox color="secondary" [checked]="isChecked" (change)="onChange($event)"> </mat-checkbox> </div> </div> <div class="displayTask"> <div class="displayvalue" [ngClass]="{ 'line-through': isChecked }"> {{ value.task | uppercase }} </div> </div>
(注:原模板里[ngClass]的判断条件value.task不符合逻辑,改成isChecked才是选中时划线的正确逻辑)
3. 修改父组件 item-list.component.ts
添加选中项数组,处理子组件发来的事件:
import { Component, OnInit } from '@angular/core'; import { FormControl } from '@angular/forms'; @Component({ selector: 'app-item-list', templateUrl: './item-list.component.html', styleUrls: ['./item-list.component.scss'], }) export class ItemListComponent implements OnInit { nameControl = new FormControl(''); data: { task: string }[] = []; // 假设你的任务数据结构为包含task字段的对象数组 arrayChecked: string[] = []; // 统一维护所有选中项 constructor() {} ngOnInit(): void {} addTask() { const task = this.nameControl.value?.trim(); if (task) { this.data.push({ task }); this.nameControl.reset(); } } onItemCheckChange(event: { task: string; checked: boolean }) { if (event.checked) { // 添加选中项,避免重复 if (!this.arrayChecked.includes(event.task)) { this.arrayChecked.push(event.task); } } else { // 移除取消选中的项 this.arrayChecked = this.arrayChecked.filter(task => task !== event.task); } console.log('所有选中项:', this.arrayChecked); } }
4. 修改父组件模板 item-list.component.html
给<app-item>绑定isChecked输入和checkChange输出事件:
<div> <mat-form-field appearance="outline"> <input matInput placeholder="Add a Task" (keyup.enter)="addTask()" autocomplete="off" [formControl]="nameControl"/> </mat-form-field> </div> <app-item [value]="value" [isChecked]="arrayChecked.includes(value.task)" (checkChange)="onItemCheckChange($event)" *ngFor="let value of data; index as index" > </app-item>
逻辑说明
- 父组件
ItemListComponent维护唯一的arrayChecked数组,所有选中项都存储在这里。 - 每个子组件
ItemComponent的选中状态由父组件通过[isChecked]传入,确保所有item的状态统一。 - 子组件触发复选框变化时,通过
checkChange事件把任务和选中状态传给父组件,父组件负责更新数组。 - 父组件在更新数组时做了去重和过滤处理,避免重复添加或残留已取消选中的项。
内容的提问来源于stack exchange,提问作者Joskaa
相关产品推荐
相关产品推荐

