如何在 angular 8 中生成动态反应形式 [英] How to generate dynamically reactive forms in angular 8

查看:31
本文介绍了如何在 angular 8 中生成动态反应形式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我提出了关于动态生成表单控制器的问题,之后我在动态模板生成和控制器生成方面遇到了一些问题.

在这个项目中,主要是我在一个数组中有4种类型的问题.我必须动态生成这些问题

问题类型是,

  1. MCQ(只需选择一个答案)

  2. 多选(用户可以选择多个答案,至少需要一个)

  3. 排名问题(用户必须给出正确的答案顺序.答案应该是unque)

  4. 描述性(用户自己的答案可以给出)

这是我的html代码

<div class="row"><div class="col-md-12"><div class="card"><div class="card-header bg-transparent border-success"><h3>15 个问题</h3>

<div class="card-body"><div class="row"><div class="col-md-12"><form [formGroup]="surveyQuestionForm"><div *ngFor="let question of questions; let i=index"><div [ngSwitch]="question.qType"><div *ngSwitchCase="1"><div class="form-group"><label class="control-label">{{question.qNo}}){{question.question}}</label><div class="ml-3"><表格><tr *ngFor="let anwr of question.answers; let a=index"><td>{{a+1}}.{{anwr}} </td><td><div class="custom-radio custom-control"><input type="radio" class="custom-control-input"id="q{{question.qNo}}_{{a}}"name="q{{question.qNo}}" value="{{a+1}}"formControlName="q{{question.qNo}}"[ngClass]="{'is-invalid':surveyQuestionForm.get('q'+ question.qNo).errors && formSubmitted}"/><label class="custom-control-label"for="q{{question.qNo}}_{{a}}"></label>

</td></tr><div class="text-danger"*ngIf="surveyQuestionForm.get('q'+ question.qNo).hasError('required') && formSubmitted">需要回答

<div *ngSwitchCase="2"><div class="form-group"><label class="control-label">{{question.qNo}}){{question.question}}</label><div class="ml-3"><表格><tr *ngFor="let anwr of question.answers; let b=index"><td>{{b+1}}.{{anwr}} </td><td><div class="custom-checkbox custom-control"><input type="checkbox" class="custom-control-input"id="q{{question.qNo}}_{{b}}" value="{{b+1}}"formControlName="q{{question.qNo}}"[ngClass]="{'is-invalid':surveyQuestionForm.get('q'+ question.qNo).errors && formSubmitted}"/><label class="custom-control-label"for="q{{question.qNo}}_{{b}}"></label>

</td></tr><div class="text-danger"*ngIf="surveyQuestionForm.get('q'+ question.qNo).hasError('atLeastOneRequired') && formSubmitted">至少需要一个答案

<div *ngSwitchCase="3"><div class="form-group"><label class="control-label">{{question.qNo}}){{question.question}}</label><div class="ml-3"><表格><tr *ngFor="let anwr of question.answers; let a=index"><td>{{a+1}}.{{anwr}} </td><div class="无效反馈"*ngIf="surveyQuestionForm.get('q'+ question.qNo).touched &&surveyQuestionForm.get('q'+ question.qNo).hasError('required')">需要回答

<div class="无效反馈"*ngIf="surveyQuestionForm.get('q'+ question.qNo).touched &&surveyQuestionForm.get('q'+ question.qNo).hasError('max')">最大值

<div class="无效反馈"*ngIf="surveyQuestionForm.get('q'+ question.qNo).touched &&surveyQuestionForm.get('q'+ question.qNo).hasError('min')">最小值

<div class="无效反馈"*ngIf="surveyQuestionForm.get('q'+ question.qNo).touched &&surveyQuestionForm.get('q'+ question.qNo).hasError('notAllUnique')">已插入值

<td><input type="number" style="width:40px;"id="q{{question.qNo}}_{{a}}"[ngClass]="{'is-invalid':surveyQuestionForm.get('q'+ question.qNo).errors&&SurveyQuestionForm.get('q'+ question.qNo).touched}"formControlName="q{{question.qNo}}"class="text-center"/></td></tr>

<div *ngSwitchCase="4"><div class="form-group"><label class="control-label">{{question.qNo}}){{question.question}}</label><div class="ml-3"><表格><th width="auto"></th><th></th><tr><td><textarea class="form-control" rows="5" id="comment" name="text"[ngClass]="{'is-invalid':surveyQuestionForm.get('q'+ question.qNo).errors &&SurveyQuestionForm.get('q'+ question.qNo).touched}"formControlName="q{{question.qNo}}"></textarea></td></tr><div class="text-danger"*ngIf="surveyQuestionForm.get('q'+ question.qNo).hasError('required') && formSubmitted">需要回答

<div *ngSwitchCaseDefault></div>

</表单>

<div class="row"><div class="col-md-12"><button (click)="onSubmit()" class="btn btn-primary">提交</button>

这是我的打字稿代码

surveyQuestionForm: FormGroup;表单提交 = 假;构造函数(私人FB:FormBuilder){}问题:任何= [{编号:11,调查编号:5,qNo: 1,问题:你想去哪个国家旅行?",qType: 1,没有答案:4,答案类型:1,答案:['美国'、'澳大利亚'、'印度'、'英格兰']},{编号:12,调查编号:5,qNo: 2,问题:'你有什么类型的信用卡?',qType: 2,没有答案:4,答案类型:1,答案:['Visa'、'Mastercard'、'American Express'、'Discover']},{编号:13,调查编号:5,qNo: 3,问题:请按重要性对以下特征进行排序,其中 1 对您来说最重要.?",qType: 3,没有答案:4,答案类型:1,答案:['位置'、'舒适'、'服务'、'物有所值']},{编号:14,调查编号:5,qNo: 4,问题:您对我们的研究所有何看法?",qType: 4,没有答案:0,答案类型:1,答案:[]}];ngOnInit() {this.createForms();}createForms(): 任何 {this.surveyQuestionForm = this.fb.group(this.questions.reduce((group: any, question: { qNo: string; }) => {return Object.assign(group, { ['q' + question.qNo]: this.buildSubGroup(question) });}, {}));}私人 buildSubGroup(问题){开关(问题.qType){情况1:返回 [Validators.required];案例2:返回 this.fb.group(question.answers.reduce((subGroup, answer) => {返回 Object.assign(subGroup, { [answer]: [false] });}, {}), { 验证器:[this.atLeastOneRequired()] });案例3:返回 this.fb.group(question.answers.reduce((subGroup, answer) => {返回 Object.assign(subGroup, { [answer]: ['', [Validators.required, Validators.min(1), Validators.max(3)]] });}, {}), { 验证器:[this.uniqueNumbersValidator()] });案例4:return this.fb.group({ answer: ['', [Validators.required]] });默认:throw new Error('未处理的问题类型');}}atLeastOneRequired() {return (ctrl: AbstractControl) =>{const fg = ctrl as FormGroup;const atLeastOneTrue = Object.values(fg.controls).some(fc => !!fc.value);返回 (atLeastOneTrue) ?null : { atLeastOneRequired: true };};}uniqueNumbersValidator() {return (ctrl: AbstractControl) =>{const fg = ctrl as FormGroup;让 allUnique = true;常量值 = [];Object.values(fg.controls).forEach(fc => {const val = fc.value;如果 (val && allUnique) {if (values.includes(val) && allUnique) {allUnique = 假;}values.push(val);}});返回(allUnique)?null : { notAllUnique: true };};}提交(){this.formSubmitted = true;console.log(this.formSubmitted);}

我可以看到这个错误,

<块引用>

control.registerOnChange 不是函数

这里是stackblitz链接https://stackblitz.com/edit/angular-nya7l9

请帮我解决这个问题.

谢谢

解决方案

首先,您的无线电构建和绑定问题:

像这样构建它:

 案例 1:案例4:return this.fb.group({ answer: ['', [Validators.required]] });

并像这样绑定:

 

<label class="control-label">{{question.qNo}}){{question.question}}</label><div class="ml-3"><表格><tr *ngFor="let anwr of question.answers; let a=index"><td>{{a+1}}.{{anwr}} </td><td><div class="custom-radio custom-control"><input type="radio" class="custom-control-input"id="q{{question.qNo}}_{{a}}"name="answer" value="{{a+1}}"表单控件名称=答案"[ngClass]="{'is-invalid':surveyQuestionForm.get('q'+ question.qNo).errors && formSubmitted}"/><label class="custom-control-label"for="q{{question.qNo}}_{{a}}"></label>

</td></tr><div class="text-danger"*ngIf="surveyQuestionForm.get('q'+ question.qNo).hasError('required') && formSubmitted">需要回答

在顶部使用 formGroupName 指令,然后静态访问答案控件.

接下来您的复选框绑定:

<label class="control-label">{{question.qNo}}){{question.question}}</label><div class="ml-3"><表格><tr *ngFor="let anwr of question.answers; let b=index"><td>{{b+1}}.{{anwr}} </td><td><div class="custom-checkbox custom-control"><input type="checkbox" class="custom-control-input"id="q{{question.qNo}}_{{b}}" value="{{b+1}}"formControlName="{{anwr}}"[ngClass]="{'is-invalid':surveyQuestionForm.get('q'+ question.qNo).errors && formSubmitted}"/><label class="custom-control-label"for="q{{question.qNo}}_{{b}}"></label>

</td></tr><div class="text-danger"*ngIf="surveyQuestionForm.get('q'+ question.qNo).hasError('atLeastOneRequired') && formSubmitted">至少需要一个答案

再次使用 formGroupName 指令,因为您的整个表单只是一组组,然后在其中,您的 formControlNames 本身就是答案.

现在你的多选绑定,一般都是一样的问题:

最后,你的自由文本答案,基本相同的问题,需要 formGroupName 指令,并正确绑定到其中的静态答案控件: