公司有项目用的是Angular Metarial风格,一直想给其中的
mat-select
组件添加搜索功能,偶然遇到ngx-mat-select-search库基本满足需求,又能够保留原有的mat-select
风格,特此记录用法。
安装:
yarn add ngx-mat-select-search
- 用法一(list数据源已请求在本地):
<mat-form-field class="w-100">
<mat-select formControlName="title" placeholder="职位">
<mat-option>
<ngx-mat-select-search
ngModel (ngModelChange)="filterTitles($event)"
[ngModelOptions]="{standalone: true}" [placeholderLabel]="'职位'"
[noEntriesFoundLabel]="'没有找到相配的数据'"
></ngx-mat-select-search>
</mat-option>
<mat-option [value]="''"
*ngIf="filteredTitles?.length === 0 ||
filteredTitles?.length === titles?.length">
全部
</mat-option>
<mat-option *ngFor="let item of filteredTitles" [value]="item">
{{item}}
</mat-option>
</mat-select>
</mat-form-field>
titleArr = this.constantService.employeeTitleArr
filteredTitles = this.constantService.employeeTitleArr
/**
* @desc 筛选职位
*/
filterTitles($event) {
if (!this.titleArr) {
return
}
if (!$event) {
this.filteredTitles = this.titleArr.slice()
return
} else {
$event = $event.toLowerCase()
}
this.filteredTitles = this.titleArr.filter(it => it.toLowerCase().indexOf($event) > -1)
}
- 用法二(需要网络请求):
<mat-form-field class="w-100">
<mat-select [placeholder]="'输入会员姓名、手机号搜索'" [formControl]="dialogForm.controls['latent']"
(openedChange)="onOpenChange($event)" required #latentSelect>
<mat-option>
<ngx-mat-select-search [formControl]="latentCtrl"
[placeholderLabel]="'会员姓名、手机号'"
[noEntriesFoundLabel]="'没有找到相配的会员'"
[searching]="searching"></ngx-mat-select-search>
</mat-option>
<mat-option *ngFor="let item of filteredLatents | async" [value]="item">
{{item.name}}({{item.phone}})
</mat-option>
</mat-select>
<mat-error *ngIf="dialogForm.controls['latent'].touched">
<span *ngIf="dialogForm.controls['latent'].hasError('required')">字段不能为空</span>
</mat-error>
</mat-form-field>
import {AfterViewInit, Component, OnDestroy, OnInit, ViewChild} from '@angular/core'
import {MatSelect} from '@angular/material'
import {FormBuilder, FormControl, FormGroup} from '@angular/forms'
import {debounceTime, filter, takeUntil, tap} from 'rxjs/operators'
import {ReplaySubject, Subject} from 'rxjs/index'
@Component({
selector: 'app-transfer-card',
templateUrl: 'transfer-card.dialog.html',
styles: [``],
})
export class LatentSelectComponent implements OnInit, AfterViewInit, OnDestroy {
dialogForm: FormGroup
latentCtrl: FormControl = new FormControl()
searching = false
filteredLatents: ReplaySubject<any[]> = new ReplaySubject<any[]>(1)
@ViewChild('latentSelect', {'static': false}) latentSelect: MatSelect
protected _onDestroy = new Subject<void>()
constructor(private fb: FormBuilder) {
this.dialogForm = fb.group({
latent: [''],
})
}
ngOnInit() {
this.searchLatents()
}
ngAfterViewInit() {
this.latentSelect.compareWith = (a: any, b: any) => a && b && a._id === b._id
}
searchLatents() {
// listen for search field value changes
this.latentCtrl.valueChanges
.pipe(
filter(search => !!search),
tap(() => this.searching = true),
takeUntil(this._onDestroy),
debounceTime(500),
)
.subscribe(filtered => {
this.httpService.findLatent({limit: 10, q: filtered})
.then(res => {
this.searching = false
if (res && res.data) {
this.filteredLatents.next(res.data)
}
})
.catch(error => {
this.searching = false
})
},
e => {
this.searching = false
})
}
// Event emitted when the select panel has been toggled.
onOpenChange(open) {
if (!open) { // 关闭选择框时判断
const events = this.filteredLatents['_events']
if (Array.isArray(events)) {
const len = events.length
if (len && events[len - 1]) {
const list = events[len - 1].value
const {latent} = this.dialogForm.value
if (Array.isArray(list) && latent) {
const find = list.find(it => it._id === latent._id)
if (!find) { // 若列表中没有被选中的model,则组装一个列表,否则界面上无法解析显示
this.filteredLatents.next([latent])
}
}
}
}
}
}
ngOnDestroy() {
this._onDestroy.next()
this._onDestroy.complete()
}
}
效果: