Angular Material 绑定到事件取消 valueChanges 订阅

Angular Material binding to event cancels valueChanges subscription

我有一个非常基本的自动完成设置 Angular Material (6)。这是基本实现:

<mat-form-field>
    <input type="text" matInput placeholder="Company" formControlName="company" [matAutocomplete]="autoCo"/>
    <mat-autocomplete #autoCo="matAutocomplete" [displayWith]="displayCo">
        <mat-option *ngFor="let company of filteredCompanies | async" [value]="company">
            {{ company.companyName }}
        </mat-option>
    </mat-autocomplete>
</mat-form-field>

这没有问题。但是,我希望在做出选择时发生一些事情。为此,我将 (optionSelected)="onSelectionChanged($event)" 添加到 mat-autocomplete 元素。最初,一切都按预期工作(过滤选项有效)。做出选择后,onSelectionChanged 函数也会按预期触发。

但是,在做出选择后,无论我做了什么更改,所选项目都是自动完成下拉列表中唯一可用的项目。所以即使我删除了输入中的所有文本,我仍然只能看到之前选择的选项。我希望看到完整的列表。

ngOnInit中,我有:

this.filteredCompanies = this.companyForm.get("company").valueChanges.pipe(
        debounceTime(200))
        .pipe(mergeMap(val => this.filter(val)));

如果我绑定到 optionSelectedvalueChanges 订阅似乎会结束。如果我不绑定到 optionSelected,选项列表会按预期更新。

我是否错误地绑定了 optionSelected 事件?我是否必须从 onSelectionChanged() 中重新订阅表单 valueChanges?如果是,为什么?

关于它的价值,这里是一些其他相关代码:

@Output()
optionSelected = new EventEmitter();

onSelectionChanged(event: any) {
    console.log(event);
    this.optionSelected.emit(event);
}

您真的订阅了 valueChanges 吗?从您的代码来看,它看起来不像。我想你错过了一个 .subscribe() 电话。

this.filteredCompanies = this.companyForm.get("company").valueChanges
  .pipe(debounceTime(200))
  .pipe(mergeMap(val => this.filter(val)))
  .subscribe(() => {});

你绑定到 onSelectionChanged 也有点不对,这个:

@Output()
optionSelected = new EventEmitter();

onSelectionChanged(event: any) {
  console.log(event);
  this.optionSelected.emit(event);
}

可以简化为:

onSelectionChanged(event: any) {
  console.log(event);
  // do what you want here
}

为了尝试回答您的问题,我首先尝试重现该问题。我创建了以下内容:

StackBlitz.

我不得不对您没有包含的代码做出一些假设,但是对于您包含的代码我没有进行实质性修改(除了偶尔添加 console.log)。

如您在 StackBlitz 中所见,您所描述的问题并未发生。

这可能与您未共享的代码有关。请将 StackBlitz 与您的代码进行比较。如果有差异,请分享不同的代码,我会更新 StackBlitz 重新测试。

一些注意事项:

  • 我刚刚为您的代码使用了默认值 'hello-component'。
  • 我创建了一个简单的 filter() 方法,因为您没有为此提供代码。
  • 我创建了一个简单的 displayCo() 方法,因为您没有提供此代码。
  • 我假设父组件通过名为 companies 的输入向该子组件提供了选项列表,这是一个 Company[].
  • 我还对您创建表单的方式做了一些假设,因为您的问题中也没有包含这些。

我希望这有助于找到问题的根本原因。

更新

您在以下评论中提供的经过编辑的 StackBlitz 代码正在调用:

this.companyForm.setControl("company", this.setCompany(newSelection));

但是 this.setCompany returns 一个 FormGroup 和 .setControl() 需要一个 FormControl 作为第二个参数。您应该能够简单地用这样的东西更新现有的 FormGroup:

this.companyForm.get('company').setValue(newSelection);

Updated StackBlitz here.