1

我正在尝试在 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 中的演示:DemoStackblitz

4

1 回答 1

2

你应该添加这一行

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

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

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

StackBlitz 上的示例解决方案

于 2021-09-07T03:31:08.870 回答