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

Angular 7 mat-autocomplete加载自动填充及动态更新数据问题

Hey there! Let's break down how to solve both of your requirements for the mat-autocomplete in Angular 7.

1. Auto-fill Data on Page Load

Right now your autocomplete only triggers when the user types at least 2 characters. To load default data when the page first loads, you need to adjust your observable stream to include an initial data fetch, and handle empty input states properly.

First, add a method to fetch default sales reps (e.g., the first 10 entries, or all if your dataset is small):

getDefaultSalesReps(): Observable<any[]> {
  const params = new QueryDto;
  params.$select = "UserId,FirstName,LastName,Username";
  params.$top = 10; // Optional: limit to top 10 results
  return from(this.salesRepresentativesService.GetSalesRepresentatives(params))
    .pipe(
      map(response => response.Data),
      catchError(() => of([])) // Return empty array on error instead of null
    );
}

Then update your salesPickerAutoComplete$ stream to merge the initial data fetch with the input change listener:

ngOnInit() {
  // Stream for initial page load data
  const initialData$ = this.getDefaultSalesReps();

  // Stream for user input changes
  const searchData$ = this.autoCompleteControl.valueChanges.pipe(
    startWith(''),
    debounceTime(400),
    distinctUntilChanged(),
    switchMap(value => {
      if (value && value.length > 2) {
        return this.getSalesReps(value);
      } else if (value === '') {
        // Refresh default data when input is cleared
        return this.getDefaultSalesReps();
      } else {
        return of([]); // Return empty array for inputs shorter than 3 chars
      }
    })
  );

  // Combine both streams: initial data first, then search results
  this.salesPickerAutoComplete$ = concat(initialData$, searchData$);

  // Optional: Auto-populate input with the first default entry
  initialData$.subscribe(data => {
    if (data.length > 0) {
      this.autoCompleteControl.setValue(data[0]);
    }
  });
}

2. Dynamically Push/Modify Autocomplete Options

To dynamically update the autocomplete options at any time (e.g., after adding a new sales rep, or refreshing data from another action), use a BehaviorSubject to control the data stream. This lets you manually push new data to the observable whenever you need.

First, define a BehaviorSubject in your component:

import { BehaviorSubject } from 'rxjs';

// ...

private salesRepsSubject = new BehaviorSubject<any[]>([]);
public salesPickerAutoComplete$ = this.salesRepsSubject.asObservable();

Then update your initialization logic to push data to the subject:

ngOnInit() {
  // Load initial data on page load
  this.getDefaultSalesReps().subscribe(data => {
    this.salesRepsSubject.next(data);
  });

  // Handle input changes
  this.autoCompleteControl.valueChanges.pipe(
    startWith(''),
    debounceTime(400),
    distinctUntilChanged()
  ).subscribe(value => {
    if (value && value.length > 2) {
      this.getSalesReps(value).subscribe(data => {
        this.salesRepsSubject.next(data);
      });
    } else if (value === '') {
      this.getDefaultSalesReps().subscribe(data => {
        this.salesRepsSubject.next(data);
      });
    } else {
      this.salesRepsSubject.next([]);
    }
  });
}

Now, whenever you need to update the options (e.g., after adding a new sales rep), just call next() on the subject with the updated array:

// Example: Add a new sales rep to the autocomplete list
addNewSalesRep(newRep: any) {
  const currentReps = this.salesRepsSubject.getValue();
  // Create a new array to trigger change detection
  const updatedReps = [...currentReps, newRep];
  this.salesRepsSubject.next(updatedReps);
}

// Example: Refresh the entire list manually
refreshSalesReps() {
  this.getDefaultSalesReps().subscribe(data => {
    this.salesRepsSubject.next(data);
  });
}

A quick safety note: In your original getSalesReps method, single quotes in user input can break your OData filter. Add a quick escape to handle this:

getSalesReps(value: string): Observable<any[]> {
  const escapedValue = value.replace(/'/g, "''"); // Escape single quotes to avoid filter errors
  const params = new QueryDto;
  params.$filter = `substringof('${escapedValue}',FirstName) or substringof('${escapedValue}',LastName)`;
  params.$select = "UserId,FirstName,LastName,Username";
  return from(this.salesRepresentativesService.GetSalesRepresentatives(params))
    .pipe(
      map(response => response.Data),
      catchError(() => of([]))
    );
}

Your template code doesn't need any changes—it will automatically update whenever the salesPickerAutoComplete$ observable emits new data.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 06:33:22