【问题标题】:Angular2 - reactive forms and multiple checkboxes not behaving correctlyAngular2 - 反应形式和多个复选框行为不正确
【发布时间】:2017-08-20 10:27:09
【问题描述】:

我仍在学习响应式表单,并且我希望为数组属性(例如爱好)设置多个复选框。所以我将组定义如下

this.myForm = this.fb.group({

    name: ['', Validators.required],

    hobbies: this.fb.array([])

});

Hobbies 是一个数组:hobbies = ['Cooking', 'Swimming', 'Hiking', 'Dancing'];

现在,在 HTML 中,我将复选框定义如下:

<div>
  <span *ngFor="let hobby of hobbies">
    <label>
      <input type="checkbox" [value]="hobby" (click)="addToHobby(hobby)"> {{hobby}}
    </label>  
    <br />
  </span>
</div>

现在,当检查一个元素时,它根本不会将它添加到 hobbies 属性中,它只是复制了实际的 HTML 元素。我做错了什么?

这是代码:https://plnkr.co/edit/j8V189VoWKvloNgwOr7p?p=preview

【问题讨论】:

  • 好吧,当用户选择一个复选框时,我希望它在 {{myForm.value | json}} 中可见,并且在取消选择时也是如此。此外,在设置模型时,应根据用户的属性选择复选框。
  • 如果你想取消选择为什么总是推送它?
  • 在示例中,即使取消选择它也会被推送到数组中。什么是正确的方法?
  • 这并不是真正的“反应式”做事方式。您不必处理事件来更新表单。

标签: angular checkbox


【解决方案1】:

好的,我设法让一些工作正常进行。链接在下面,但首先,这是我的思路。

首先,我们只需要定义一个包含所有值的数组,可能我们从 Web 服务中获取它,但我仍然像这样模拟它们:

hobbies = [new Hobby(1, 'Cooking'), new Hobby(2, 'Swimming'), new Hobby(3, 'Hiking'), new Hobby(4, 'Dancing')]; 我也特意添加了 id,所以它会更准确地模仿现实世界。现在,我们需要定义表单。由于多复选框不起作用,我决定表示一个单独的复选框数组,每个复选框都有几个属性,但至少有两个是必需的:决定数组中的复选框是否被选中的布尔值和一个名称,以便我们知道我们正在选择什么。

为了实现这一点,我们首先需要创建一个适合表单的数组,操作如下:

let hobbiesArray = [];

for (let hobby of this.hobbies) {
  hobbiesArray.push(this.fb.group({
    isChosen: false,
    name: hobby.hobbyName,
    id: hobby.id
  }));
}

很明显,我为每个爱好创建了新的fb.group,它们都放在一个数组中。然后使用这个数组来创建表单,如下:

this.myForm = this.fb.group({
  hobbiesList: this.fb.array(hobbiesArray)
});

现在我们有了fb.groups 中的fb.array。现在,当谈到 HTML 时,我有几个问题。 逻辑是“通过myForm.hobbiesList 并操作isChosen,同时保持name 只读 - 有点。这是代码。

<div formArrayName="hobbiesList">
  <div *ngFor="let hobby of hobbiesList.controls; let i=index" [formGroupName]="i" >
    <input type="checkbox" formControlName="isChosen" /> {{hobby.controls.name.value}}
  </div>
</div> 

这是我的担忧:我可以像这样称呼这个名字吗:{{hobby.controls.name.value}}?这有什么害处?我是否违反了任何 Angular2/4 规则?

好的,所以,当确认选择的爱好时,我们得到带有名称和ids(没有isChosen值)的实际数组,如下所示:

submitMe(): void {
    let items = this.myForm.value;
    this.mySelectedHobbies = items.hobbiesList.filter(x => x.isChosen).map(x => { return { name: x.name, id: x.id }; });
}

是的,这是我的设计。我不确定这是否允许我所做的一切,但我发现这是解决问题的最简单方法。大家觉得呢?

这是代码:https://plnkr.co/edit/8OKiQMK788R2uCt2OWzm?p=preview

【讨论】:

  • 我一直在寻找相同的行为,最后我得到了与您在此处描述的完全相同的模式,目前看来这是要走的路;至少对我来说似乎没有打破任何角度规则。 (拨打form.reset时请注意)
  • 感谢您的意见!我想我设法让它好一点。它基于这个解决方案:netbasal.com/… 所以在检查了他的方法之后,我可以稍微调整一下,所以最终结果在这里:plnkr.co/edit/q4C576xJCRIFCVyMxDeX?p=preview 我认为它比我原来的解决方案要好一些,因为我没有解决像这样的名称:{{hobby.controls.name.value}} 而是像这样:{{mockSkills[i].name}} 我不知道哪种方法更好。对所有这些方法有什么想法吗?
  • 这是我的最终替代版本,具有更新/插入功能。请随时更改/编辑代码,我相信有很多可以改进的地方。 plnkr.co/edit/hmKVFOQZhajgAldJGPlb?p=preview
猜你喜欢
  • 2017-08-22
  • 2017-12-29
  • 2019-12-07
  • 1970-01-01
  • 2017-04-29
  • 2019-04-01
  • 2017-12-22
  • 2021-11-09
  • 2017-11-13
相关资源
最近更新 更多