Angular 6およびMaterial 6を使用したシンプルなページを開発しています。
公式の例から https://material.angular.io/components/autocomplete/overview サービスを使用してオートコンプリートと統合する方法がわかりません。
誰も私を助けることができますか?
ありがとう
最後に、やりたいことの解決策を見つけました! FormArrayをmat-table dataSourceにバインドするには:
<table mat-table [dataSource]="itemsDataSource">
<ng-container matColumnDef="itemName">
<td mat-cell *matCellDef="let element">{{ element.value.material?.name }}</td>
</ng-container>
<ng-container matColumnDef="itemCount">
<td mat-cell *matCellDef="let element">{{ element.value.itemCount }}</td>
</ng-container>
<tr mat-row *matRowDef="let row; columns: itemColumns;"></tr>
</table>
そしてコード:
export class ItemListComponent implements OnInit {
constructor(
private fb: FormBuilder
) { }
itemColumns = ['itemName', 'count'];
itemForm: FormGroup;
itemsDataSource = new MatTableDataSource();
get itemsForm() {
return this.itemForm.get('items') as FormArray;
}
newItem() {
const a = this.fb.group({
material: new FormControl(), //{ name:string }
itemCount: new FormControl() // number
});
this.itemsForm.Push(a);
this.itemsDataSource._updateChangeSubscription(); //neccessary to render the mat-table with the new row
}
ngOnInit() {
this.itemForm = this.fb.group({
items: this.fb.array([])
});
this.newItem();
this.itemsDataSource.data = this.itemsForm.controls;
}
}
iyourAwesomeDataのような構造を持つオブジェクトとしてサーバーからurデータを返すuを想定してみましょう。この例の目的のために、フィールドsomeNameを使用してデータをフィルタリングします。
したがって、URTSコンポーネントは次のようになります。
import { Component, OnInit, OnDestroy } from '@angular/core';
import { FormControl } from '@angular/forms';
import { startWith, debounceTime, map, switchMap, distinctUntilChanged } from 'rxjs/operators';
import { Subscription } from 'rxjs';
interface IyourAwesomeData {
someName: string;
someField: string;
someOtherField: number;
}
export class YourAutcompleteComponent implements OnInit, OnDestroy {
dataFiltered: IyourAwesomeData[]; // this data will be used inside HTML Template
data: Observable<IyourAwesomeData[]>;
yourInputCtrl = new FormControl();
private sub: Subscription;
constructor() {}
ngOnInit() {
this.data = ??? // Pass your data as Observable<IyourAwesomeData[]>;
this.sub = this.yourInputCtrl.valueChanges
.pipe(
debounceTime(500),
distinctUntilChanged(),
startWith(''),
switchMap((val) => {
return this.filterData(val || '');
})
).subscribe((filtered) => {
this.dataFiltered = filtered;
});
}
ngOnDestroy() {
this.sub.unsubscribe();
}
filterData(value: string) {
return this.data // like IyourAwesomeData[]
.pipe(
map((response) => response.filter((singleData: IyourAwesomeData) => {
return singleData.someName.toLowerCase().includes(value.toLowerCase())
})),
);
}
}
また、ur HTMLテンプレートは次のようになります。
<mat-form-field>
<input matInput placeholder="some placeholder" [matAutocomplete]="auto" [formControl]="yourInputCtrl">
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let single of dataFiltered" [value]="single.someName">
{{ single.someName }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
ユーザーが入力値を変更するとすぐに、サーバーデータからoptions
を入力する必要があります。
_<input type="text" matInput (input)="onInputChanged($event.target.value)" [matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let option of options" [value]="option">{{ option.title }}</mat-option>
</mat-autocomplete>
_
コンポーネントファイルでは、onInputChanged(searchStr)
とoptions
を処理する必要があります。
_onInputChanged(searchStr: string): void {
this.options = [];
if (this.subscription) {
this.subscription.unsubscribe();
}
this.subscription = this.yourService.getFilteredData(searchStr).subscribe((result) => {
this.options = result;
});
}
_