角度动态表单嵌套字段
Posted
技术标签:
【中文标题】角度动态表单嵌套字段【英文标题】:Angular dynamic form nested fields 【发布时间】:2019-04-05 14:41:30 【问题描述】:在https://angular.io/guide/dynamic-form 的帮助下,我正在制作一个动态表单,我首先需要显示两个字段。
new TextboxQuestion(
key: 'firstName',
label: 'First name',
value: '',
required: true,
order: 1
),
new TextboxQuestion(
key: 'lastName',
label: 'Last name',
value: '',
required: true,
order: 2
),
这两个字段需要在加载时首先出现。
在此之后,我将有两个按钮作为add and remove
。
<button (click)="addNew()"> Add </button>
<button (click)="removeNew()"> Remove </button> <br><br>
通过点击添加,我需要显示接下来的两个字段(以下字段),
new TextboxQuestion(
key: 'emailAddress',
label: 'Email',
type: 'email',
order: 3
),
new DropdownQuestion(
key: 'brave',
label: 'Bravery Rating',
options: [
key: 'solid', value: 'Solid',
key: 'great', value: 'Great',
key: 'good', value: 'Good',
key: 'unproven', value: 'Unproven'
],
order: 4
)
订单 1 和 2 处于初始状态,点击添加后需要显示下两个订单 3 和 4。
请帮我实现点击添加按钮添加子字段的结果。
一次显示所有工作的堆栈闪电战,https://stackblitz.com/edit/angular-x4a5b6
【问题讨论】:
【参考方案1】:用formArray实现动态表单
嗯,事情更复杂。我做了一个stackblik,见demo
我将尝试解释如何扩展 https://angular.io/guide/dynamic-form 以允许表单数组。
首先我们需要创建一个新类型的问题,一个 questionArray
import QuestionBase from './question-base';
export class ArrayQuestion extends QuestionBase<string>
controlType = 'array';
type: any;
constructor(options: = )
super(options);
我们必须更改问题库以添加新属性“children”
export class QuestionBase<T>
value: T;
...
children:any[];
constructor(options:
value?: T,
...
children?:any
= )
this.value = options.value;
...
this.children=options.children || null;
添加更改问题控制服务以允许管理 formArrays
toFormGroup(questions: QuestionBase<any>[])
let group: any = ;
questions.forEach(question =>
//If the control type is "array" we create a FormArray
if (question.controlType=="array")
group[question.key]=new FormArray([]);
else
group[question.key] = question.required ? new FormControl(question.value || '', Validators.required)
: new FormControl(question.value || '');
);
return new FormGroup(group);
好吧,我们将 dynamic-form.component 转换为显示一个 FormArray
<div *ngFor="let question of questions" class="form-row">
<ng-container *ngIf="question.children">
<div [formArrayName]="question.key">
<div *ngFor="let item of form.get(question.key).controls; let i=index" [formGroupName]="i">
<div *ngFor="let item of question.children">
<app-question [question]="item" [form]="form.get(question.key).at(i)"></app-question>
</div>
</div>
</div>
</ng-container>
<ng-container *ngIf="!question.children">
<app-question [question]="question" [form]="form"></app-question>
</ng-container>
</div>
就这样吧。那么,如何增加和减少 formArrays?我们有两个按钮
<button (click)="addControls('myArray')"> Add </button>
<button (click)="removeControls('myArray')"> Remove </button> <br><br>
还有两个函数addControls和removeControls
addControls(control: string)
let question: any = this.questions.find(q => q.key == control);
let children = question ? question.children : null;
if (children)
(this.form.get(control) as FormArray).push(this.qcs.toFormGroup(children))
removeControls(control: string)
let array=this.form.get(control) as FormArray;
array.removeAt(array.length-1);
更新我忘了添加问题和示例:
let questions: QuestionBase<any>[] = [
new TextboxQuestion(
key: 'firstName',
label: 'First name',
value: '',
required: true,
order: 1
),
new TextboxQuestion(
key: 'lastName',
label: 'Last name',
value: '',
required: true,
order: 2
),
new ArrayQuestion(
key: 'myArray',
value: '',
order: 3,
children: [
new TextboxQuestion(
key: 'emailAddress',
label: 'Email',
type: 'email',
order: 3
),
new DropdownQuestion(
key: 'brave',
label: 'Bravery Rating',
options: [
key: 'solid', value: 'Solid' ,
key: 'great', value: 'Great' ,
key: 'good', value: 'Good' ,
key: 'unproven', value: 'Unproven'
],
order: 4
)
]
)
];
【讨论】:
Eliseo 非常感谢.. 我希望在看到 stackblitz 之后一切都会好起来.. 如果有任何疑问会回复给你.. Eliseo,我已经发布了另一个问题***.com/questions/53113962/… 以从 JSON 加载数据作为输入,它只是您的解决方案,但我需要单独为每个输入提供 JSON 数据。如果您参考你会很好理解的问题..你能帮我吗?? 嗨,Eliseo,这是您***.com/questions/53220425/… 的另一个新问题,用于在编辑期间将数据修补到这些表单元素..【参考方案2】:您唯一需要的是使用切片和变量“页面”对问题“分页”
即:
//add a variable "page" in your dinamic-form.component.ts
page:number=0;
和
//in your dinamic-form.component.html, change the *ngFor like
<form (ngSubmit)="onSubmit()" [formGroup]="form">
<div *ngFor="let question of questions.slice(page*2,(page+1)*2)" class="form-row">
<app-question [question]="question" [form]="form"></app-question>
</div>
....
</form>
然后,你的按钮添加可以像
<button (click)="page=page+1"> Add </button>
【讨论】:
感谢您的帮助.. 请提供可以帮助我的 stackblitz.. 我已经实现了您的代码,但我无法获得任何输入 stackblitz.com/edit/angular-x4a5b6 您忘记添加属性“页面”。在您的 dinamic-form.component.ts 中,您需要在指令之后添加 page:number=0:payLoad='' 如果我单击添加,那么旧的输入文本框将被隐藏,接下来的两个即将到来。我需要在初始时显示前两个,然后单击添加,接下来的两个应该会出现向下并再次单击添加添加的两个文本框(顺序 3 和 4)需要在每次单击添加时绑定。我需要在单击添加按钮时显示两个顺序(1 和 2)。我希望你在半路帮助我..请Eliseo我请求你帮助我,这将更加明显.. 只需将切片替换为切片(0,(page+1)*2)。这个想法是,您不会在每个时刻都只显示您需要的所有“问题”。我想你想每次只显示两个 只是最后一个问题。再次单击添加时,我应该在每次单击添加按钮时附加顺序(3 和 4)。您是唯一帮助我的人很多..请单独回答这个..我一定会接受你的回答..以上是关于角度动态表单嵌套字段的主要内容,如果未能解决你的问题,请参考以下文章