Angular Material の複数選択オートコンプリート
23946 ワード
最近のクライアントの場合、「検索可能な」選択が必要でした.彼らは、他のアプリケーションで使用されている機能と一致させたいと考えていました.元の検索可能な選択は、最新の Angular アプリケーションにうまく適合しない従来の jQuery オブジェクトでした.
私が必要としていたのは、複数行の選択を可能にする選択タイプのドロップダウンと、ユーザーが検索として入力した文字列でリストを絞り込む機能でした.
これが私が思いついたものです...複数選択のオートコンプリートです.
Working Example
GitHub Repo
HTML から始めて... これらは、背後にあるロジックをより理解しやすくするために順不同で表示されます.
これは、 Material の入力が
選択を表示するために Material チップ リストを追加しました.通常、このコードは他のコードの上にあるため、オートコンプリート ドロップダウンの下に隠れません.このリストでは、クリックでチップを削除することもできます.
そして、これは
CSS は非常に簡単です...サイズと色がいくつかあります.
繰り返しますが、読みやすくするためにこのコードを分割してみます.
これらのほとんどは非常に簡単です...
データポイント、入力、および出力は次のとおりです.
今、私は
さらに、
これら 2 つの関数は、上記の HTML オブジェクトで直接使用されます.
ここでは、選択した項目のみを含む単純な文字列の配列を再構築する必要がありました.
このコードは冗長に思えますが、私の考えでは、機能を明確に記述した方がよいでしょう.
ここでは、入力を渡し、出力された
イベント
Working Example
GitHub Repo
これは作成するのにクールなコンポーネントであり、良い挑戦でした.見た目だけでなく、機能性にも満足しています.
私が必要としていたのは、複数行の選択を可能にする選択タイプのドロップダウンと、ユーザーが検索として入力した文字列でリストを絞り込む機能でした.
これが私が思いついたものです...複数選択のオートコンプリートです.
コード
Working Example
GitHub Repo
HTML
HTML から始めて... これらは、背後にあるロジックをより理解しやすくするために順不同で表示されます.
入力
これは、 Material の入力が
selectControl
に関連付けられたフォーム フィールドです.<mat-form-field class="full-width">
<input matInput type="text"
[placeholder]="placeholder"
[matAutocomplete]="auto"
[formControl]="selectControl">
</mat-form-field>
チップリスト
選択を表示するために Material チップ リストを追加しました.通常、このコードは他のコードの上にあるため、オートコンプリート ドロップダウンの下に隠れません.このリストでは、クリックでチップを削除することもできます.
<div class="chip-list-wrapper">
<mat-chip-list #chipList>
<ng-container *ngFor="let select of selectData">
<mat-chip class="cardinal-colors" (click)="removeChip(select)">
{{ select.item }}
<mat-icon class="mat-chip-remove">cancel</mat-icon>
</mat-chip>
</ng-container>
</mat-chip-list>
</div>
オートコンプリート
そして、これは
filterdata
に関連付けられた Material オートコンプリートです.<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
<mat-option *ngFor="let data of filteredData | async">
<div (click)="optionClicked($event, data)">
<mat-checkbox [checked]="data.selected"
(change)="toggleSelection(data)"
(click)="$event.stopPropagation()">
{{ data.item }}
</mat-checkbox>
</div>
</mat-option>
</mat-autocomplete>
CSS
CSS は非常に簡単です...サイズと色がいくつかあります.
.full-width {
width: 100%;
}
.chip-list-wrapper {
min-height: 3em;
}
.msac-colors {
background-color: var(--primary-color);
color: white;
}
TypeScript
繰り返しますが、読みやすくするためにこのコードを分割してみます.
輸入品
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Observable } from 'rxjs';
import { map, startWith } from 'rxjs/operators';
import { ItemData } from '@core/interfaces/multi-select-item-data';
これらのほとんどは非常に簡単です...
ItemData
には定義が必要です...インターフェースを見て...export interface ItemData {
item: string;
selected: boolean;
}
コンポーネントラッパー
@Component({
selector: 'multiselect-autocomplete',
templateUrl: './multiselect-autocomplete.component.html',
styleUrls: ['./multiselect-autocomplete.component.scss']
})
export class MultiselectAutocompleteComponent implements OnInit {
...
}
データ設定
データポイント、入力、および出力は次のとおりです.
@Output() result = new EventEmitter<{ key: string, data: Array<string> }>();
@Input() placeholder: string = 'Select Data';
@Input() data: Array<string> = [];
@Input() key: string = '';
selectControl = new FormControl();
rawData: Array<ItemData> = [];
selectData: Array<ItemData> = [];
filteredData: Observable<Array<ItemData>>;
filterString: string = '';
placeholder
と data
の構造はかなり明確です. key
が渡され、変更されずに出力されます.これにより、外部の (呼び出し元の) コードは、どのオブジェクトにアタッチするかを知ることができます.初期化
constructor() {
this.filteredData = this.selectControl.valueChanges.pipe(
startWith<string>(''),
map(value => typeof value === 'string' ? value : this.filterString),
map(filter => this.filter(filter))
);
}
ngOnInit(): void {
this.data.forEach((item: string) => {
this.rawData.push({ item, selected: false });
});
}
今、私は
data
入力を取り、ブール値として選択された一致する rawData
を生成しています.さらに、
filteredData
を selectControl
値の変更にバインドしています.これが、上記の HTML で async
が必要な理由です.フィルタおよび表示機能
これら 2 つの関数は、上記の HTML オブジェクトで直接使用されます.
filter = (filter: string): Array<ItemData> => {
this.filterString = filter;
if (filter.length > 0) {
return this.rawData.filter(option => {
return option.item.toLowerCase().indexOf(filter.toLowerCase()) >= 0;
});
} else {
return this.rawData.slice();
}
};
displayFn = (): string => '';
オプションがクリックされました
optionClicked = (event: Event, data: ItemData): void => {
event.stopPropagation();
this.toggleSelection(data);
};
optionClicked
は、読みやすくするためにこのように名前が付けられ、構成されています.選択を切り替え
toggleSelection = (data: ItemData): void => {
data.selected = !data.selected;
if (data.selected === true) {
this.selectData.push(data);
} else {
const i = this.selectData.findIndex(value => value.item === data.item);
this.selectData.splice(i, 1);
}
this.selectControl.setValue(this.selectData);
this.emitAdjustedData();
};
toggleSelection
はトグルし、 selectData
から値を追加/削除し、変更されたデータを出力します.調整済みデータの発行
emitAdjustedData = (): void => {
const results: Array<string> = []
this.selectData.forEach((data: ItemData) => {
results.push(data.item);
});
this.result.emit({ key: this.key, data: results });
};
ここでは、選択した項目のみを含む単純な文字列の配列を再構築する必要がありました.
チップの取り外し
このコードは冗長に思えますが、私の考えでは、機能を明確に記述した方がよいでしょう.
removeChip = (data: ItemData): void => {
this.toggleSelection(data);
};
複数選択オートコンプリートの使用
HTML
ここでは、入力を渡し、出力された
result
をキャプチャする関数を設定しました.<multiselect-autocomplete
[placeholder]="structure[index].subtitle"
[data]="cardSelects[card.key]"
[key]="card.key"
(result)="selectChange($event)">
</multiselect-autocomplete>
TypeScript
イベント
key
と data
が出力され、ここで使用されます.selectChange = (event: any) => {
const key: string = event.key;
this.cardValue[key] = [ ...event.data ];
};
コード
Working Example
GitHub Repo
概要
これは作成するのにクールなコンポーネントであり、良い挑戦でした.見た目だけでなく、機能性にも満足しています.
Reference
この問題について(Angular Material の複数選択オートコンプリート), 我々は、より多くの情報をここで見つけました https://dev.to/rfornal/angular-material-multi-select-autocomplete-kpgテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol