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];
}
我正在尝试使用 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];
}