Ng-Select - Select/Unselect 使用 ControlValueAccessor 接口的自定义组件中的所有项目

Ng-Select - Select/Unselect all items in custom component using the ControlValueAccessor interface

我正在尝试使用 ng-select 和 controlValueAccessor 界面包装设置 multiselect(为每个选项使用复选框)组合所需的所有配置。

到目前为止它有点工作,除了如果我通过放置在列表顶部的复选框选择 select 或取消 select 所有项目,只有表单中的值被更新,而不是控件中的 selection。

当我单独 select 或取消 select 项目时,控件仅按预期工作,然后控件和表单值都相应更新:

这是可重用组件的代码:

TypeScript

import { Component, Input, OnInit, Self, ViewChild } from '@angular/core';
import { ControlValueAccessor, NgControl } from '@angular/forms';

@Component({
  selector: 'app-multi-select',
  templateUrl: './multi-select.component.html',
  styleUrls: ['./multi-select.component.css']
})
export class MultiSelectComponent implements OnInit, ControlValueAccessor {

  disabled: boolean;
  selectedValues: any;

  @Input() optionItems: any[];
  @ViewChild('combo', { static: true }) combo;
  constructor(@Self() public controlDir: NgControl) {
    this.controlDir.valueAccessor = this;
  }

  ngOnInit(): void {
  }

  toggleCheckAll(values: any) {
    if (values.currentTarget.checked) {
      this.selectAllItems();
    } else {
      this.unselectAllItems();
    }
  }
  onChange(event) {
    debugger;
  }

  onTouched() {}

  onSelectionChange(selectedItems) {
    debugger;
    if (Array.isArray(selectedItems)) {
      const newList = selectedItems.map((x) => x.id);
      this.selectedValues = [...newList]
      this.onChange([...newList]);
    }
    this.onTouched();
  }

  writeValue(obj: any): void {
    this.combo.select([...obj]);
  }
  registerOnChange(fn: any): void {
    this.onChange = fn;
  }
  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }
  setDisabledState?(isDisabled: boolean): void {
    this.disabled = isDisabled;
  }

  private selectAllItems() {
    const newList = this.optionItems.map((x) => x.id);
    this.selectedValues = [...newList];
    this.onChange([...newList]);
  }

  private unselectAllItems() {
    this.selectedValues = [];
    this.onChange([]);
  }

}

HTML

<ng-select 
  #combo
  [multiple]="true" 
  [items]="optionItems"
  [closeOnSelect]="false"
  (change)="onSelectionChange($event)"   
  (blur)="onTouched()"    
  placeholder="Select people"
    bindLabel="name"
  bindValue="id">

    <ng-template ng-header-tmp let-items="items">
        <input type="checkbox"  (change)="toggleCheckAll($event)"/>
        </ng-template>

        <ng-template ng-multi-label-tmp let-items="items" let-clear="clear">
            <div class="ng-value" *ngFor="let item of items | slice:0:2">
                <span class="ng-value-label">{{item.name}}{{item.login}}</span>
                <span class="ng-value-icon right" (click)="clear(item)" aria-hidden="true">×</span>
            </div>
            <div class="ng-value" *ngIf="items.length > 2">
                <span class="ng-value-label">{{items.length - 2}} more...</span>
            </div>
        </ng-template>

        <ng-template ng-option-tmp let-item="item" let-item$="item$" let-index="index">
            <input id="item-{{index}}" type="checkbox" [checked]="item$.selected" /> {{item.name}}
    </ng-template>
</ng-select>

您可以在 this demo on stackblitz

中找到完整代码

顺便说一句:我不得不在 onSelectionChange 中放置一个条件来检查传入的参数是否为数组,因为令我惊讶的是,即使我使用 change 事件也会被调用复选框放在列表的顶部,不仅当我 select 或取消 select 个别选项时。

您可以使用 ngModel 指令将所选值绑定到 ng-select。

试试这个:

<ng-select #combo [multiple]="true" [items]="optionItems" [closeOnSelect]="false" (change)="onSelectionChange($event)"
    (blur)="onTouched()" placeholder="Select people" bindLabel="name" [ngModel]="selectedValues" bindValue="id">

    <ng-template ng-header-tmp let-items="items">
        <input type="checkbox" [ngModel]="checkAll"  (change)="toggleCheckAll($event)"/>
        </ng-template>

        <ng-template ng-multi-label-tmp let-items="items" let-clear="clear">
            <div class="ng-value" *ngFor="let item of items | slice:0:2">
                <span class="ng-value-label">{{item.name}}{{item.login}}</span>
                <span class="ng-value-icon right" (click)="clear(item)" aria-hidden="true">×</span>
            </div>
            <div class="ng-value" *ngIf="items.length > 2">
                <span class="ng-value-label">{{items.length - 2}} more...</span>
            </div>
        </ng-template>

        <ng-template ng-option-tmp let-item="item" let-item$="item$" let-index="index">
            <input id="item-{{index}}" type="checkbox" [checked]="item$.selected" /> {{item.name}}
    </ng-template>
</ng-select>

然后在您的 class 中将值设置为 selectedValue,如下所示:

component.ts

 writeValue(obj: any): void {
    this.selectedValues =[...obj];
  }