使用 formArray 时出现 Mat-AutoComplete 错误

Mat-AutoComplete error when using formArray

我添加了一个 formarray 来说明多行。为了使它与索引一起工作,我必须将我的定义从 shoppingCartList Observable<any[]>; 更改为 shoppingCartList: Observable<any[]>[] = []; 但是当我这样做时它会在我的过滤器函数中抛出一个错误 missing the following properties from type 'Observable<any[]>[]': length, pop, push, concat。看起来是因为我正在调用一项服务来过滤列表。实现这个的正确方法是什么: .HTML

<mat-autocomplete #auto="matAutocomplete" [displayWith]="entry">
       <mat-option *ngFor="let case of shoppingCartList[i] | async" [value]="case">
            {{title}}
         </mat-option>
 </mat-autocomplete>

.TS

    shoppingCartList: Observable<any[]>[] = [];
            
             this.shoppingCartList[index] = arrayControl.at(index).get('name').valueChanges //ERROR: (property) DraftformComponent.filteredPrimaryCaseSerial: Observable<any[]>[]
    Type 'Subscription' is missing the following properties from type 'Observable<any[]>

                .pipe(debounceTime(this.debounceTime))
                  .subscribe(
                    (val) => {
                        this.filteredList= this.getFilteredlist(val); //ERROR: (property) DraftformComponent.filteredPrimaryCaseSerial: Observable<any[]>[]
    Type 'Observable<any[]>' is missing the following properties from type 'Observable<any[]>[]
                      }
                  );
        
         public getFilteredList(val: string): Observable<any[]> {
            return this.myService.getListByValue(val);
          }

如果我正确地看到你的代码,你就订阅了 observable。因此,您在模板中获取的不是数组值,而是订阅。您应该删除 subscribe 方法以使模板正常工作,或者您将值保存在 subscribe 方法中并在没有可观察对象的情况下使用它。 我不完全理解您想对示例中的“filteredList”做什么,但是您可以将代码包装在 tap 运算符 https://rxjs.dev/api/operators/tap

首先,您看到错误的原因是您输入列表的方式。

Observable<any[]>[] = [];

你在这里告诉编译器你的购物车列表的类型是一个由多个 observables 数组组成的数组。

所以,错误 missing the following properties from type 'Observable<any[]>[]': length, pop, push, concat 只是告诉你,你所说的 getFilteredList 将 return 实际上不是函数所期望的 return --它期望 return 一个 数组的可观察对象 (任何类型)。

这与使用服务过滤列表无关。当您提到在这种情况下使用表单数组来解释多行时,我也有点不确定您的意思。

考虑到这一点 - 根据您的问题,我认为您的目标是这样的。

  /**
   * Define a form which contains your FormControl you wish
   * to use for your autocomplete.
   */

  form = new FormGroup({
    shoppingListSearch: new FormControl()
  });

像这样访问它:

  get shoppingListSearch(): FormControl {
    return this.form.get('shoppingListSearch') as FormControl;
  }

FormControls 将它们的值变化公开为可观察的,方便地称为 valueChanges。您的尝试已经走在了正确的轨道上!

与其手动订阅 observables,我会使用 Angular 的模板。它管理在销毁组件时为您整理订阅。如果您像上面那样手动订阅可观察对象,并且不取消订阅,您将留下订阅,导致内存泄漏。

像这样定义一个可观察对象:

  filteredList$: Observable<
    ShoppingListItem[]
  > = this.shoppingListSearch.valueChanges.pipe(
    debounceTime(1000),
    // Use a switchMap here to subscribe to the inner observable.
    // This is assuming your filtering needs to make a HTTP request.
    // switchMap will maintain one inner subscription, so should you 
    // make another request while one is in flight, the in flight 
    // request will be cancelled and a new one made with your new
    // search term.  
    switchMap((searchTerm: string) =>
      // this can be whatever filtering logic you want I guess.
      // To reiterate, I used a switchMap above as getFilteredList
      // returns an observable. An operator like map or tap wouldn't 
      // work here, as they don't handle subscribing to inner observables.
      this.myService.getFilteredList(searchTerm)
    )
  );

这是模板:

<form class="example-form" [formGroup]="form">
  <mat-form-field appearance="fill">
    <mat-label>Search...</mat-label>
    <input
      class="example-full-width"
      placeholder="Search for something..."
      formControlName="shoppingListSearch"
      [matAutocomplete]="auto"
      matInput
    />
  </mat-form-field>

  <mat-autocomplete #auto="matAutocomplete" [displayWith]="entry">
    <!-- Here is where we subscribe to the filtered list observable -->
    <mat-option *ngFor="let shoppingItem of filteredList$ | async" [value]="shoppingItem.name">
      {{shoppingItem.name}}
    </mat-option>
  </mat-autocomplete>
</form>

这是 StackBlitz