Angular - 在 mat-select 中实现 NgxMatSelectSearch

Angular - Implement NgxMatSelectSearch in mat-select

我正在尝试使用 mat-select 中的搜索框,该搜索框仅在使用默认加载的数据时才能正常工作。我想使用来自 api 的数据。但是不能正常工作,加载页面时数据不显示在mat-select中,但是当焦点出现在mat-select标签中时显示。

我有一个模型,我在其中使用来自测试的数据 API

export interface DataModel {
  id: number;
  title: string;
  userId: number;
}

export const DataModels: DataModel[] = [
  { id: 1, title: 'Option A', userId: 23 },
  { id: 2, title: 'Option B', userId: 24 },
  { id: 3, title: 'Option C', userId: 25 },
  { id: 4, title: 'Option D', userId: 26 }
];

我打电话的服务

@Injectable()
export class DataloadService {
  constructor(private http: HttpClient) {}

  LoadData(): Observable<any> {
    return this.http.get('https://jsonplaceholder.typicode.com/albums');
  }
}

执行搜索过滤器和设置控件的组件。按照文档 NgxMatSelectSearch

constructor(private service: DataloadService) {}
  dataModel: DataModel[] = []; //DataModels
  dataCtrl: FormControl = new FormControl();
  dataFilterCtrl: FormControl = new FormControl();
  filteredData: ReplaySubject<DataModel[]> = new ReplaySubject<DataModel[]>(1);
  @ViewChild('singleSelect', { static: true }) singleSelect: MatSelect;

  _onDestroy = new Subject<void>();

  ngOnInit() {
    this.load();
    this.filteredData.next(this.dataModel.slice());
    this.dataFilterCtrl.valueChanges
      .pipe(takeUntil(this._onDestroy))
      .subscribe(() => {
        this.filterData();
      });
  }

  ngOnDestroy() {
    this._onDestroy.next();
    this._onDestroy.complete();
  }

  filterData() {
    if (!this.dataModel) {
      return;
    }
    let search = this.dataFilterCtrl.value;
    if (!search) {
      this.filteredData.next(this.dataModel.slice());
      return;
    } else {
      search = search.toLowerCase();
    }
    this.filteredData.next(
      this.dataModel.filter(
        (x: any) => x.title.toLowerCase().indexOf(search) > -1
      )
    );
  }
  load() {
    return this.service.LoadData().subscribe(res => {
      this.dataModel = res;
    });
  }

还有 HTML

<mat-card>
  <mat-toolbar>Demo</mat-toolbar><br />
  <mat-card-content>
    <mat-select [formControl]="dataCtrl" placeholder="Data" #singleSelect>
      <mat-option>
        <ngx-mat-select-search
          [formControl]="dataFilterCtrl"
        ></ngx-mat-select-search>
      </mat-option>

      <mat-option *ngFor="let x of filteredData | async" [value]="x.id">
        {{x.title}}
      </mat-option>
    </mat-select>
  </mat-card-content>
</mat-card>

如果我使用模型中默认的数据来模拟使用“dataModels”的过程

dataModel: DataModel[] = []; //DataModels

而不是将其初始化为空。它工作正常,但如果我根据对 API 的请求加载数据,就会出现焦点发生后未加载数据的问题。

我在 Stackblitz 中的演示:Demo Stackblitz

你应该添加这一行

this.filteredData.next(this.dataModel.slice());

进入 this.service.LoadData()subscribe 事件,因为它是异步的。这样当返回响应结果时,filteredData与响应结果绑定。

load() {
  return this.service.LoadData().subscribe(res => {
    this.dataModel = res;
    this.filteredData.next(this.dataModel.slice());
  });
}

Sample Solution on StackBlitz