Angular中点击按钮如何显示筛选后的已勾选待办项列表
解决待办列表筛选已勾选项的显示问题
你目前已经实现了已勾选项目的收集,但核心问题在于没有将筛选状态与视图渲染绑定,同时子组件的状态管理和父组件的数据同步存在逻辑漏洞。以下是针对性的修复方案:
1. 修正子组件(ItemComponent)的状态同步逻辑
子组件不应独立维护IsChecked状态,而应与父组件传入的待办项状态绑定,避免数据不一致:
item.component.ts
import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core'; export class ItemComponent implements OnInit { @Input() value: any; // 从父组件传入的状态初始化,而非固定为false IsChecked: boolean = this.value.isChecked; @Output() checkTask = new EventEmitter<any>(); // 补充定义缺失的removeCheck事件 @Output() removeCheck = new EventEmitter<any>(); constructor() {} ngOnInit(): void { // 组件初始化时同步父组件状态 this.IsChecked = this.value.isChecked; } onChange($event: any, name: any) { this.IsChecked = $event.checked; if ($event.checked) { this.checkTask.emit({...this.value, isChecked: true}); } else { this.removeCheck.emit({...this.value, isChecked: false}); } } removeTask($event: any) { // 补充删除逻辑(若需要) } }
item.component.html
修正按钮标签和样式绑定错误:
<div class="listContainer"> <div class="checkContainer" [style.backgroundColor]="IsChecked ? 'grey' : '#ff6165'" > <div> <mat-checkbox color="secondary" [(ngModel)]="IsChecked" (change)="onChange($event, value.task)" ></mat-checkbox> </div> </div> <div class="displayTask"> <!-- 样式绑定改为判断IsChecked,而非任务内容 --> <div class="displayvalue" [ngClass]="{ 'line-through': IsChecked }"> {{ value.task | uppercase }} </div> </div> <div class="menuDrop"> <!-- 修正Matbutton为小写mat-button --> <button mat-icon-button [matMenuTriggerFor]="menu"> <mat-icon>more_vert</mat-icon> </button> <mat-menu #menu="matMenu"> <button mat-menu-item (click)="removeTask($event)"> <mat-icon class="deleteitem">delete</mat-icon> <span>remove</span> </button> </mat-menu> </div> </div>
2. 父组件(ItemListComponent)实现筛选状态绑定
使用BehaviorSubject管理筛选状态,结合异步管道自动更新视图,无需手动维护筛选后的数组:
item-list.component.ts
import { Component, OnInit } from '@angular/core'; import { BehaviorSubject, combineLatest, Observable } from 'rxjs'; import { map } from 'rxjs/operators'; // 定义待办项类型 interface TaskType { task: string; isChecked: boolean; } export class ItemListComponent implements OnInit { // 存储所有待办项的源数据 private tasksSubject = new BehaviorSubject<TaskType[]>([]); private tasks$ = this.tasksSubject.asObservable(); // 筛选状态:true=仅显示已勾选,false=显示全部 private showOnlyCheckedSubject = new BehaviorSubject<boolean>(false); private showOnlyChecked$ = this.showOnlyCheckedSubject.asObservable(); // 最终供视图渲染的筛选后数据 public filteredData$: Observable<TaskType[]>; public nameControl = new FormControl(''); // 补充定义FormControl ngOnInit(): void { // 组合源数据和筛选状态,自动生成筛选结果 this.filteredData$ = combineLatest([this.tasks$, this.showOnlyChecked$]).pipe( map(([tasks, showChecked]) => { return showChecked ? tasks.filter(task => task.isChecked) : tasks; }) ); } // 添加新任务 addTask() { const newTask = { task: this.nameControl.value, isChecked: false }; const currentTasks = this.tasksSubject.value; this.tasksSubject.next([...currentTasks, newTask]); this.nameControl.reset(); } // 切换筛选状态 displaylist() { const currentState = this.showOnlyCheckedSubject.value; this.showOnlyCheckedSubject.next(!currentState); } // 更新已勾选任务状态 addCheckedTask($event: TaskType) { this.updateTaskStatus($event); } // 更新取消勾选的任务状态 removeCheckedTask($event: TaskType) { this.updateTaskStatus($event); } // 通用更新任务状态方法 private updateTaskStatus(updatedTask: TaskType) { const currentTasks = this.tasksSubject.value; const index = currentTasks.findIndex(task => task.task === updatedTask.task); if (index !== -1) { currentTasks[index] = updatedTask; this.tasksSubject.next([...currentTasks]); } } // 删除任务逻辑 removeTask(data: TaskType[], index: number) { const updatedTasks = data.filter((_, i) => i !== index); this.tasksSubject.next(updatedTasks); } // 拖拽排序逻辑(保留原有代码) drop($event: any, data: TaskType[]) { // 原有拖拽实现 } }
item-list.component.html
无需修改现有渲染逻辑,异步管道会自动根据筛选状态更新视图:
<div> <mat-form-field appearance="outline"> <input matInput placeholder="Add a Task" (keyup.enter)="addTask()" autocomplete="off" [formControl]="nameControl" /> </mat-form-field> <button (click)="displaylist()">Display Checked</button> </div> <ng-container *ngIf="filteredData$ | async as data"> <div cdkDropList class="example-list" (cdkDropListDropped)="drop($event, data)" > <app-item [value]="value" *ngFor="let value of data; index as index" (inputDataChange)="removeTask(data, index)" (checkTask)="addCheckedTask($event)" (removeCheck)="removeCheckedTask($event)" cdkDrag > </app-item> </div> </ng-container>
核心改进点说明
- 状态统一管理:所有待办项的勾选状态存储在父组件的源数组中,子组件仅做状态同步,避免数据不一致
- 响应式筛选:通过
BehaviorSubject和combineLatest实现筛选状态与源数据的自动关联,视图自动更新 - 简化逻辑:无需单独维护
arrayChecked数组,直接从源数组筛选已勾选项,减少冗余代码
内容的提问来源于stack exchange,提问作者Joskaa
相关产品推荐
相关产品推荐

