您的代码中有几个错误。
您指出的最后一个堆栈闪电战(来自this SO)是一种“富有想象力”的方式来管理一系列复选框以提供存储字符串数组的 formControl。这个想法是输入有[checked] 和(change),但是NOT formControlName(这是因为一开始复选框变成了“已选中”)。 formControl 在表单中没有输入。是的,formControl 存在,但没有输入。
复选框的[checked] 是一个函数,指示“选项”是否包含在控件的值中(使用 indexOf)
(change) 具有参数、索引 - 用于本地化 formControl-、“选项”的值以及是否选中。
一个more simple stackblitz 来展示这个概念:
<!--see that "answer" has no input, it's only a variable in .ts-->
<div *ngFor="let option of options">
<input #check type="checkbox"
[checked]="answer.indexOf(option)>=0"
(change)="onChange(option,check.checked)"
>
{{option}}
</div>
answer=["check 2"]
options=["check 1","check 2","check3"]
onChange(option:string,checked:boolean)
{
if (checked && this.answer.indexOf(option)<0)
this.answer=[...this.answer,option]
.sort((a,b)=>this.options.indexOf(a)>this.options.indexOf(b)?1:-1)
if (!checked)
this.answer=this.answer.filter(x=>x!=option)
}
好吧,在你的代码中
1.-改变表单(请看代码中的cmets)
<div *ngIf="form.type == 'checkbox'">
<p>{{form.title}}</p>
<div *ngFor="let option of form.options">
<!--in your code WRONG (change)="onChange(i,j, form.code,check.checked)" -->
<!-- see that we need send the "option", not the form.code-->
<label><input #check (change)="onChange(i,j, option,check.checked)"
<!--use checked, not value, and remove the "toString"-->
[checked]="answers[i].value.forms[j].answer.indexOf(option)>=0"
<!--see that we has no formControlName="answer" -->
type="checkbox">{{option}}</label>
</div>
</div>
函数onChange,它只是如果checked=true 添加“代码”,如果checked=false 删除“代码”。好吧,有一个困难是“排序”响应。为了对响应进行排序,我们比较“选项”中的 indexOf 值
我使用辅助变量“options”来获取“options”
2.-改变你的函数 onChange by
onChange(indexi: number, indexj: number, code: string, isChecked: boolean) {
const control = this.answerArray.at(indexi).get("forms")["controls"][indexj]
.controls.answer;
const options=this.listFormField[indexi].sectionItems[indexj].options
//options will be, eg. ["check 1","check 2","check 3"]
if (isChecked && control.value.indexOf(code) < 0)
control.setValue(
[...control.value, code].sort((a: string, b: string) =>
options.indexOf(a) >options.indexOf(b)
? 1
: -1
)
);
if (!isChecked && control.value.indexOf(code) >= 0)
control.setValue(control.value.filter(x => x != code));
}
注意:您需要修改代码,实际上,当您创建表单时,您所有的“答案”都是数组(只需将它们是复选框的“答案”数组)
已更新为避免在 answer 为 null 时出现错误,我们可以或避免在创建表单时,或者另一种选择,将代码更改为选中为
[checked]="(answers[i].value.forms[j].answer || []).indexOf(option)>=0"
路径值我们可以,如果只是一个元素,例如
const i=0
const j=1
this.response.get('answers.'+i+'.forms.'+j+'.answer')
.patchValue(["check 1","check 2"])
是的,要获得“答案”,我们可以通过索引使用“get”。也许这很容易理解,因为当我们使用 formGroup 的 formArray 时,我们会写 [formGroupName]="i"。如果我们想在 FormGroup 上创建 pathValue,我们需要考虑,如果我们在数组上创建 pathValue,pathValue 不会将元素添加到 formArray,因此如果我们发送更多元素,则不会添加它。此外,如果我们发送更少的元素,pathValue,删除元素
考虑到这一点,我们也可以制作,例如
this.response.get('answers.'+i+'.forms')
.patchValue(
[
{answer:"radio 2"},
{answer:["check 1","check 2"]},
{answer:"text input"},
{answer:"text area"},
{answer:["check 6"]},
]
)