这真的很难调试,但基本上问题是,当mat-option
在虚拟卷轴的渲染窗口之外时,该选项将不会被选中,所以我编写了一个特殊的切片方法,它将始终将选定的库放置在数组的顶部,因此肯定会被选中,这解决了您的问题.
getCorrectSlice(): Bank[] {
const output = this.banks.slice();
const bank: Bank = this.bankCtrl.value;
if (bank) {
return [bank, ...this.banks];
}
return this.banks.slice();
}
上面的代码创建了在开始处具有所选值的切片!
HTML
<h3>Single selection</h3>
<p>
<mat-form-field>
<mat-select
id="bank"
id="bank"
[formControl]="bankCtrl"
placeholder="Bank"
#singleSelect
[compareWith]="compareWith"
(selectionChange)="selectionChange($event)"
>
<mat-option>
<ngx-mat-select-search
[formControl]="bankFilterCtrl"
></ngx-mat-select-search>
</mat-option>
<!-- <mat-option *ngFor="let bank of filteredBanks | async" [value]="bank">
{{bank.name}}
</mat-option> -->
<cdk-virtual-scroll-viewport [itemSize]="42" [style.height.px]="4 * 42">
<mat-option [value]="{ name: 'any', id: -1 }">Any</mat-option>
<mat-option
*cdkVirtualFor="let bank of filteredBanks | async; trackBy: trackBy"
[value]="bank"
>{{ bank.name }}</mat-option
>
</cdk-virtual-scroll-viewport>
</mat-select>
</mat-form-field>
</p>
<p>Selected Bank: {{ bankCtrl.value?.name }}</p>
TS
import {
AfterViewInit,
Component,
OnDestroy,
OnInit,
ViewChild,
} from '@angular/core';
import { FormControl } from '@angular/forms';
import { MatSelect } from '@angular/material/select';
import { ReplaySubject, Subject } from 'rxjs';
import { take, takeUntil } from 'rxjs/operators';
import { Bank, BANKS } from '../demo-data';
@Component({
selector: 'app-single-selection-example',
templateUrl: './single-selection-example.component.HTML',
styleUrls: ['./single-selection-example.component.scss'],
})
export class SingleSelectionExampleComponent
implemenTS OnInit, AfterViewInit, OnDestroy
{
/** list of banks */
protected banks: Bank[] = BANKS;
/** control for the selected bank */
public bankCtrl: FormControl = new FormControl();
/** control for the MatSelect filter keyword */
public bankFilterCtrl: FormControl = new FormControl();
/** list of banks filtered by search keyword */
public filteredBanks: ReplaySubject<Bank[]> = new ReplaySubject<Bank[]>(1);
@ViewChild('singleSelect', { static: true }) singleSelect: MatSelect;
/** Subject that emiTS when the component has been destroyed. */
protected _onDestroy = new Subject<void>();
constructor() {}
ngOnInit() {
// set initial selection
// load the initial bank list
this.bankCtrl.setValue(this.banks[10]);
this.filteredBanks.next(this.getCorrectSlice());
// listen for search field value changes
this.bankFilterCtrl.valueChanges
.pipe(takeUntil(this._onDestroy))
.subscribe(() => {
this.filterBanks();
});
}
ngAfterViewInit() {}
ngOnDestroy() {
this._onDestroy.next();
this._onDestroy.complete();
}
getCorrectSlice(): Bank[] {
const output = this.banks.slice();
const bank: Bank = this.bankCtrl.value;
if (bank) {
return [bank, ...this.banks];
}
return this.banks.slice();
}
compareWith(a: Bank, b: Bank) {
return a && a.name && b && b.name ? a === b : false;
}
protected filterBanks() {
let search = this.bankFilterCtrl.value;
if (!this.banks || !search) {
return;
}
// get the search keyword
if (!search) {
this.filteredBanks.next(this.getCorrectSlice());
return;
} else {
search = search.toLowerCase();
}
// filter the banks
this.filteredBanks.next(
this.banks.filter((bank) => bank.name.toLowerCase().indexOf(search) > -1)
);
}
selectionChange(e: any) {
this.bankFilterCtrl.setValue('');
this.filteredBanks.next(this.getCorrectSlice());
}
trackBy(index: number, item: Bank) {
return item.id;
}
}
stackblitz