首页 > 解决方案 > 为什么我不能从我的组件中设置 Angular Material 单选组的值?

问题描述

我已经两次与这个问题搏斗了,所以我把它放在这里提醒未来的我。如果有人有更优雅的解决方案,我很乐意将其标记为答案。

我正在开发一个可以将选项显示为单选按钮或复选框的组件。一切都很好,直到我尝试添加取消功能,我发现我无法从组件的取消功能中设置单选按钮。当我检查绑定到 Angular Material 单选组的变量的值时,它在开发工具中看起来正确,但它没有显示在屏幕上选择的正确选项。

这是一个带有示例的闪电战:https ://radio-group-example.stackblitz.io

当它第一次出现时,它会要求您选择 Rush 乐队中您最喜欢的成员。它默认为 Neil Peart。选择您想要的任何人,它会在顶部显示他们的名字。但是,如果您单击“Pick Geddy”按钮,您会看到他的名字正确显示,但没有选择单选按钮。

Geddy 是否被选中?

此外,如果您从单选按钮切换到复选框并使用“切换小部件”按钮返回,它会清除所有选择。您可以选择成员并使用复选框查看他们的姓名,但如果您尝试“Pick Geddy”按钮,您会看到它显示了他的姓名,但没有选中任何复选框。

下面是选择 Geddy 的函数:

private changeToGeddy() {
  let weinrib = { name: 'Geddy Lee', id: 'GL' };
  if (this.mutuallyExclusive) {
    this.selectedOptions = weinrib;
  } else {
    this.selectedOptions = [weinrib];
  }
}

问题是:当绑定变量看起来具有正确的值时,为什么不显示单选按钮或复选框的选择?另外,复选框和单选按钮之间的切换与问题有什么关系?

标签: data-bindingangular-materialradio-group

解决方案


这里有两个问题 - 一个与在互斥选项(单选按钮)和多个选项(复选框)之间切换有关。另一个与绑定到对象或数组有关。

这是一个带有解决方案的闪电战:https ://radio-group-example-solution.stackblitz.io

在同一小部件​​中管理单选按钮和复选框

首先,我在组件中有一个 Options 数组,如下所示:

options: Option[] = [
  { name: 'Geddy Lee', id: 'GL' },
  { name: 'Alex Lifeson', id: 'AL' },
  { name: 'Neil Peart', id: 'RP' }
];

还有一个 selectedOptions 变量供组件绑定。ngOnInit() 函数设置它,如下所示:

selectedOptions: Option | Option[];
...
ngOnInit(){
  this.mutuallyExclusive = true;
  this.selectedOptions = this.options[2];
}

在这里,this.selectedOptions可以是 Option 对象或 Option 对象的数组。在这种情况下,我将 eachmat-radio-button的值设置为一个对象。使用单选按钮的mat-radio-group值更新绑定变量 - 在本例中为 Option 对象。

但是,我用于复选框的mat-selection-list小部件不是绑定到对象,而是绑定到对象数组。它更新数组以包含当前选定对象的集合。首先让我遇到这个问题的原因是试图跟踪this.selectedOptions是对象还是对象数组。

this.selectedOptions相反,始终是一个数组要容易得多。将 绑定mat-radio-group到该数组中的第一个点,如下所示:

<mat-radio-group name="ralph" [(ngModel)]="selectedOptions[0]">
  <mat-radio-button *ngFor="let option of options" [value]="option">
    {{ option.name }}
  </mat-radio-button>
</mat-radio-group>

这样我的组件更容易阅读,因为我可以摆脱处理确定我是绑定到对象还是数组的逻辑。因此,如果您在单个组件中处理这两种小部件,这是管理它的一种方法。

通过引用设置选定的变量

另一个问题是我试图通过将组件设置为具有相同键和值的对象而不是使用对原始选项的引用来设置组件的值。

即使对象的键和值相同,Angular Material 也不认为它是同一个对象。如果您的选项集来自一个数组,要以编程方式设置它,您需要通过指向实际选项来完成它,而不是它的相同克隆。因此,这会导致控件正确反映绑定变量的值:

private changeToGeddy() {
  let weinrib = this.options[0];
  this.selectedOptions = [weinrib];
}

该函数更短且更易于阅读,因为我们总是绑定到一个数组。(我们并不真正需要let那里的语句,但它强调了我们通过引用而不是对象来设置它的事实。)


推荐阅读