You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>

核心改进点说明

  1. 状态统一管理:所有待办项的勾选状态存储在父组件的源数组中,子组件仅做状态同步,避免数据不一致
  2. 响应式筛选:通过BehaviorSubject和combineLatest实现筛选状态与源数据的自动关联,视图自动更新
  3. 简化逻辑:无需单独维护arrayChecked数组,直接从源数组筛选已勾选项,减少冗余代码

内容的提问来源于stack exchange,提问作者Joskaa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 02:35:55