Angular 动态表单嵌套字段
Angular dynamic form nested fields
在 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。
请帮助我实现在点击添加按钮时添加子字段的结果。
一次显示所有的工作 stackblitz,https://stackblitz.com/edit/angular-x4a5b6
您唯一需要的是 "paginate" 您使用切片和变量的问题 "page"
即:
//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>
使用 formArray 实现动态表单。
嗯,事情比较复杂。我制作了一个 stackblik,请参阅 demo
我将尝试解释如何扩展 https://angular.io/guide/dynamic-form 以允许表单数组。
首先我们需要 make 创建一个新的问题类型,一个 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
})
]
})
];
在 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。
请帮助我实现在点击添加按钮时添加子字段的结果。
一次显示所有的工作 stackblitz,https://stackblitz.com/edit/angular-x4a5b6
您唯一需要的是 "paginate" 您使用切片和变量的问题 "page"
即:
//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>
使用 formArray 实现动态表单。
嗯,事情比较复杂。我制作了一个 stackblik,请参阅 demo
我将尝试解释如何扩展 https://angular.io/guide/dynamic-form 以允许表单数组。
首先我们需要 make 创建一个新的问题类型,一个 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
})
]
})
];