使用 formArray 时出现 Mat-AutoComplete 错误
Posted
技术标签:
【中文标题】使用 formArray 时出现 Mat-AutoComplete 错误【英文标题】:Mat-AutoComplete error when using formArray 【发布时间】:2021-09-11 03:12:34 【问题描述】:我添加了一个表单数组来处理多行。为了使它与索引一起工作,我必须将我的定义从: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);
【问题讨论】:
我不知道到底想做什么。您是否有自动完成组件,并且当字段更改时,您希望填充过滤选项以显示服务数据? 是的,没错,但是因为它在表单数组中,所以它变得很棘手。我基于这个例子:stackblitz.com/edit/… 我认为,如果您稍微重构一下代码,您正在尝试做的事情会容易得多。您可以尝试创建您的设置的堆栈闪电战吗?我会做到这一点,这样您就没有任何可观察到的要传递给自动完成功能。处理所有数据,然后在组件中为处理后的数据设置一个变量,然后在 *ngFor 中使用该变量。我认为你应该从那个开始 听起来您正在使用服务来过滤数组。我假设你正在做一个自动完成,从服务器获得接下来的几个建议,对吗?你不应该需要一个 observable 的数组。看看这个问题的第二个答案:***.com/questions/57852645/… 是的,这是正确的@ChadK,如果有意义的话,我必须添加一个数组才能跟踪 formArray 中多行的用户数据。我是基于this 示例 【参考方案1】:首先,您看到错误的原因是您输入列表的方式。
Observable<any[]>[] = [];
您已经在这里告诉编译器,您的购物车列表的类型是由多个可观察对象组成的数组。
所以,错误 missing the following properties from type 'Observable<any[]>[]': length, pop, push, concat
只是告诉您,您所说的 getFilteredList
将返回的内容实际上并不是函数期望返回的——它期望返回一个 可观察的数组 em>(任何类型)。
这与使用服务过滤列表无关。当您提到在这种情况下使用表单数组来解释多行时,我也有点不确定您的意思。
考虑到这一点 - 根据您的问题,这就是我认为您的目标。
/**
* 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;
FormControl
s 将它们的值更改公开为可观察的,方便地称为valueChanges
。您的尝试已经走在正确的轨道上!
我会使用 Angular 的模板,而不是手动订阅 observables。它在销毁组件时为您管理订阅的整理。如果您像上面那样手动订阅 observables,并且不取消订阅,您将留下订阅,导致内存泄漏。
像这样定义一个可观察对象:
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。
【讨论】:
【参考方案2】:如果我正确地看到了你的代码,你就订阅了 observable。因此,您不会在模板中获得数组值,而是在订阅中。您应该删除 subscribe 方法以使模板正常工作,或者将值保存在 subscribe 方法中并在没有 observables 的情况下使用它。 我不完全理解您想在示例中使用“filteredList”做什么,但您可以将代码包装在点击运算符 https://rxjs.dev/api/operators/tap
【讨论】:
以上是关于使用 formArray 时出现 Mat-AutoComplete 错误的主要内容,如果未能解决你的问题,请参考以下文章
在服务中使用 FormArray 时的 OnPush 更改检测