You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Observable数据源实现Angular Material可筛选Autocomplete?

结合Angular Material Autocomplete与Observable数据源(基于自定义Store)

直接上实现方案,分组件类、模板、模块配置三部分,结合你提供的CoinApiStore完成对接:

1. 组件类实现

在组件中引入响应式表单控件和CoinApiStore,通过监听输入框的valueChanges触发Store的筛选逻辑:

import { Component, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Observable } from 'rxjs';
import { startWith, switchMap } from 'rxjs/operators';
import { CoinApiStore } from './path-to/coin-api-store.service';
import { Asset } from './path-to/asset.interface';

@Component({
  selector: 'app-asset-autocomplete',
  templateUrl: './asset-autocomplete.component.html',
  styleUrls: ['./asset-autocomplete.component.css']
})
export class AssetAutocompleteComponent implements OnInit {
  assetControl = new FormControl('');
  filteredAssets$!: Observable<Asset[]>;

  constructor(private coinApiStore: CoinApiStore) {}

  ngOnInit(): void {
    this.filteredAssets$ = this.assetControl.valueChanges.pipe(
      // 初始加载时显示默认的前10条数据
      startWith(''),
      // 每次输入变化时调用Store的筛选方法,自动切换Observable
      switchMap(value => this.coinApiStore.getFilteredData(value?.toLocaleUpperCase() || ''))
    );
  }

  // 自定义下拉选项的显示文本(适配Asset结构)
  displayAsset(asset: Asset): string {
    return asset ? (asset.name || asset.asset_id) : '';
  }
}

2. 模板实现

使用Angular Material的mat-autocomplete组件,绑定到我们定义的filteredAssets$,关联表单控件完成交互:

<mat-form-field appearance="fill">
  <mat-label>选择资产</mat-label>
  <input type="text" matInput [formControl]="assetControl" [matAutocomplete]="auto">
  <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayAsset">
    <mat-option *ngFor="let asset of filteredAssets$ | async" [value]="asset">
      {{ asset.name || asset.asset_id }}
    </mat-option>
  </mat-autocomplete>
</mat-form-field>

3. 模块配置

确保你的模块中导入了必要的Angular Material和响应式表单模块:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { AssetAutocompleteComponent } from './asset-autocomplete.component';

@NgModule({
  declarations: [AssetAutocompleteComponent],
  imports: [
    CommonModule,
    ReactiveFormsModule,
    MatFormFieldModule,
    MatInputModule,
    MatAutocompleteModule
  ],
  exports: [AssetAutocompleteComponent]
})
export class AssetAutocompleteModule {}

对Store代码的小优化建议

你当前的Store中private subject是冗余的,因为data$直接被赋值为接口请求的返回值,可简化为:

import { Injectable } from '@angular/core';
import { map, Observable, shareReplay } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { Asset } from '../interfaces/coin-api/asset';

@Injectable({
    providedIn: 'root'
})
export class CoinApiStore {

    private data$: Observable<Asset[]>;

    constructor(private http: HttpClient) {
        this.data$ = this.getDataFromCoinApi().pipe(shareReplay(1));
    }

    public getData(): Observable<Asset[]> {
        return this.data$.pipe(
            map(assets => assets.sort(this.sortAssets).slice(0, 10))
        );
    }

    public getFilteredData(value: string): Observable<Asset[]> {
        return this.data$.pipe(
            map(assets => assets.filter(asset => asset.name?.toLocaleUpperCase().includes(value)).sort(this.sortAssets).slice(0, 10))
        );
    }

    private getDataFromCoinApi(): Observable<Asset[]> {
        const key = process.env['API_KEY'];
        const url = `https://rest.coinapi.io/v1/assets?apikey=${key}`;
        return this.http.get<Asset[]>(url);
    }

    private sortAssets(a1: Asset, a2: Asset) {
        return (a1.name ?? a1.asset_id).localeCompare((a2.name ?? a2.asset_id));
    }

}

内容的提问来源于stack exchange,提问作者Kiran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 18:33:23