【问题标题】:Angular Reactive Form patchValue() doesn't fill input connected to mat-autocompleteAngular Reactive Form patchValue() 不填充连接到 mat-autocomplete 的输入
【发布时间】:2019-07-05 13:17:00
【问题描述】:

我正在尝试重新填充使用 mat-autocomplete 的输入。但是,每当我使用this.optionForm.patchValue({selectedOption: 'my value'}) 发送值时,结果都不会显示在 GUI 中。如果我console.log()我可以清楚地看到设置的值。我不确定这个问题是否与我有时将一个对象设置到字段中而其他时间只设置一个字符串这一事实有关?但我希望能够用结果重新填充输入并适当地显示它。无论我如何尝试,我似乎都无法显示结果。

下面是我的组件,它只包含有问题的输入,我的 Observable 正在为mat-autocomplete 获取结果。这些在第一次使用表单时工作正常。

// component.html
<mat-form-field>
<mat-label>Option Object</mat-label>
<input type="text" matInput formControlName="selectedOption" required
       [matAutocomplete]="autoGroup">
<mat-autocomplete #autoGroup="matAutocomplete"
                  (optionSelected)="updateOptionInfo($event.option.value)"
                  [displayWith]="displayFn">
    <mat-option *ngFor="let result of resultOptions | async" [value]="result">
        <span>{{result}}</span>
    </mat-option>
</mat-autocomplete>

// component.ts
this.resultOptions = this.optionForm.get('selectedOption').valueChanges
        .pipe(
            debounceTime(300),
            switchMap(value => {
                if (value === '') {
                    this.clearProviderInfo();
                    return of(null);
                }
                if (value !== '' && ((typeof value) !== 'object')) {
                    return this.optionService.fetchAndFilterOptions(value)
                        .pipe(
                            catchError((e) => {
                                console.error(e);
                                return of([]); // empty list on error
                            })
                        );
                } else {
                    return of(null);
                }
            })
        );

任何帮助将不胜感激!

【问题讨论】:

  • stackblitz 将使我们更容易帮助解决此问题
  • 在更新resultOptions后试试这个this.resultOptions = [...this.resultOptions]
  • @AbhishekKumar 是一个 Observable,所以 Typescript 抱怨:Type 'any[]' is not assignable to type 'Observable&lt;any[]&gt;'.   Property '_isScalar' is missing in type 'any[]'.
  • @AkberIqbal 好主意!我将添加一个堆栈闪电战!

标签: angular angular-material observable angular-reactive-forms mat-autocomplete


【解决方案1】:

方法一:
使用setTimeout达到想要的效果,如下使用-

setTimeout(()=>{
      this.optionForm.patchValue({selectedOption: 'test'});
}, 0);

方法 2:
这种方法在没有async 的情况下有效

    //-----in component.html file, without async-------
        *ngFor="let result of resultOptions"


   // -------in component.ts file---------
    this.optionForm.get('selectedOption').valueChanges
        .pipe(
            debounceTime(300),
            switchMap(value => {
                if (value === '') {
                    this.clearInfo();
                    return of(null);
                }
                if (value !== '' && ((typeof value) !== 'object')) {
                    return of(this.pretendOptions);
                } else {
                    return of(null);
                }
            })
        ).subscribe(e=>this.resultOptions = e);

        //--- value is updated after subscribing to the `valueChanges`.    
        this.optionForm.patchValue({selectedOption: 'test'}); 

Demo without async operator

【讨论】:

  • 感谢您提出的解决方案;但是,这不是问题。我在其他回复中描述的问题是显示函数为不存在的属性返回 null。
  • 问题中的 @daswolle 和 stackblitz 假设在更新可观察数组后选项未显示在选择框中,因此我相应地回答了问题。但是,如果问题已经解决,那就没问题了。
  • 是的,谢谢@abhishek,感谢您的意见。这些问题和反馈有助于澄清一切!
【解决方案2】:

我创建了一个堆栈闪电战来重现该问题:

https://stackblitz.com/edit/material-6-gh3rmt?file=app/app.component.ts

这样做我意识到问题所在!通过显示函数返回对象的某些属性,它显然会为字符串显示为空。所以对象正在被设置并且可以在表单中看到,但是因为我使用了自定义显示函数,所以它被字符串上的 null 属性运行。

希望我可以帮助将来可能遇到此问题的其他人!

充实这个解决方案:

  displayFn(x) {
    return x.name; // if name doesn't exist this will obviously return null!
  }

因此,解决方法是在所选内容不是具有.name 属性的对象的情况下进行备份:

if ((typeof x) === 'string') {
    return x;
}
return x ? x.name : undefined;

【讨论】:

  • 非常好...我们都可以了解到,重新创建一个最小的、可验证的示例通常会使核心问题浮出水面,从而更容易解决:)
  • @daswolle,感谢您提供 stackblitz,但它应该在更新的问题中,不应该作为答案发布,因为它不是解决方案而是问题扩展。谢谢你。请查看我的回答并评论问题,以便我们删除问题以解决问题。
  • @AbhishekKumar 你说得对,stackblitz 目前并不代表解决方案。我将更新这篇文章,以更具体地解决所提出的问题。
  • @daswolle 感谢您将此作为问题的答案,这对其他人会有所帮助。
猜你喜欢
  • 2023-03-20
  • 2023-03-22
  • 2019-01-04
  • 2019-01-09
  • 2019-01-17
  • 2022-10-20
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多