首页 > 解决方案 > 复选框列表上的全选功能

问题描述

我有一个项目列表及其相关的复选框。

我想实现以下目标:

这些步骤中的大多数都按预期工作,除非我:

这会导致我在单击“全选”复选框之前未选中的任何列表项保持未选中状态。

在此处输入图像描述

在这种情况下,看起来(由于某种原因)复选框的内部状态没有改变。

虽然,当:

它正确选择了所有列表项。所以我有点困惑,为什么它在上面提到的另一种情况下不起作用。

注意:主要原因,我不想为列表中的每个项目存储状态,是我将在带有虚拟滚动的表中使用它。它逐页获取数据。所以我无法访问所有项目数据,因此,我只存储我手动选择或未选择的项目。

app.component.ts

import { Component, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent {

  constructor( private cdr: ChangeDetectorRef ) {
    this.cdr.markForCheck();
  }

  public list = [
    "item1", "item2", "item3", "item4", "item5"
  ];

  public selected = {
    ids: [],
    all: false,
    all_except_unselected: false
  };

  public toggleSelectItem( id: number, event: MouseEvent ): void {
    if ( this.selected.all === true ) {
      this.selected.all = false;
      this.selected.all_except_unselected = true;
      this.selected.ids = [];
    }

    if ( this.selected.all_except_unselected === true ){
      this.selected.ids = [ ...this.selected.ids, id ];
    } else if ( this.selected.all == false && this.selected.all_except_unselected == false ) {
      if ( this.selected.ids.indexOf( id ) === -1 ) {
        this.selected.ids = [ ...this.selected.ids, id ];
      } else {
        this.selected.ids = [ ...this.selected.ids].filter( itemId => itemId !== id );
      }
    }
    console.log(this.selected.ids);
  }

  public isSelected( id: number ): boolean {
    if ( this.selected.all === true ) {
      console.log(id, 'selected all')
      return true;
    } else if ( this.selected.all_except_unselected === true ) {
      console.log(id, 'selected all except unselected');
      return true;
    }

    console.log(id, this.selected.ids.indexOf( id ) >= 0 ? 'selected' : 'unselected');
    return this.selected.ids.indexOf( id ) >= 0;
  }

  public toggleSelectAll(): void {

    if ( this.selected.all == false ) {
      this.selected.ids = [];
    }
    this.selected.all = !this.selected.all;
    this.selected.all_except_unselected = false;
    console.log('selected all ', this.selected );
  }
}

app.component.html

<input type="checkbox" [checked]="selected.all" (change)="toggleSelectAll()"> Select All 
<br>
<br>

 <div *ngFor="let item of list; let i = index" >
   <input type="checkbox" [checked]="isSelected(i)" (change)="toggleSelectItem(i, $event)"> {{ item }}<br>
 </div>

旧代码链接

解决方案

标签: javascripthtmlangularcheckbox

解决方案


代码真的很乱。我不会打扰布尔值,您可以即时检查数组,复选框将正确更新状态。

这是更新的代码,您可以进行进一步修改,但您可以了解它是如何工作的。

https://angular-hvbfai.stackblitz.io

import { Component, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent {

  constructor(private cdr: ChangeDetectorRef) {
    this.cdr.markForCheck();
  }

  public list = [
    "item1", "item2", "item3", "item4", "item5"
  ];

  public selected = {
    ids: []
  };

  public allSelected() {
    return this.selected.ids.length === this.list.length;
  }
  public toggleSelectItem(id: number, event: MouseEvent): void {
    if (this.selected.ids.indexOf(id) === -1) {
      this.selected.ids = [...this.selected.ids, id];
    } else {
      this.selected.ids = [...this.selected.ids].filter(itemId => itemId !== id);
    }

    console.log(this.selected.ids);
  }

  public isSelected(id: number): boolean {
    return this.selected.ids.indexOf(id) >= 0;
  }

  public toggleSelectAll(): void {

    if (this.allSelected()) {
      this.selected.ids = [];
    } else {
      let i = 0;
      this.list.forEach(element => {
        if (this.selected.ids.indexOf(i) === -1) {
          this.selected.ids = [...this.selected.ids, i];
        }
        i++;
      });
    }
    console.log('selected all ', this.selected);
  }
}

HTML:

<input type="checkbox" [checked]="allSelected()" (change)="toggleSelectAll()"> Select All 
<br>
<br>

 <div *ngFor="let item of list; let i = index" >
   <input type="checkbox" [checked]="isSelected(i)" (change)="toggleSelectItem(i, $event)"> {{ item }}<br>
 </div>

推荐阅读