How to combine two parts of single form in angular?
Solution 1
You can take several aproach
1.-Create a formJoin that was {form1:questions of form1,form2:questions of form2}
In your ngOnInit
formJoin:FormGroup;
ngOnInit()
{
this.questions = this.service.getQuestions(this.jsonDataPart1)
this.form = this.qcs.toFormGroup(this.questions);
this.questionsPartTwo = this.service.getQuestions(this.jsonDataPart2)
this.formPartTwo = this.qcs.toFormGroup(this.questionsPartTwo);
this.formJoin=new FormGroup({form1:this.form,form2:this.formPartTwo})
}
//In your .html
<form (ngSubmit)="onSubmit()" [formGroup]="formJoin">
2.-Join the question in an unique json
this.allquestions=this.service.getQuestions(
this.jsonDataPart1.concat(this.jsonDataPart2));
this.formJoin2=this.qcs.toFormGroup(this.allquestions);
//get the first question.key in the second form
this.questionBreak=this.jsonDataPart2[0].key;
//In your .html
<form (ngSubmit)="onSubmit()" [formGroup]="formJoin2">
<h4> <b> An uniq Form </b> </h4>
<div *ngFor="let question of allquestions" class="form-row">
<!--make a break fro the secondForm-->
<ng-container *ngIf="question.key==questionBreak">
<h4> <b> Form Part Two begins from here </b> </h4>
</ng-container>
<ng-container>
<app-question [question]="question" [form]="formJoin2"></app-question>
</ng-container>
</div>
</form>
IMPORTANT NOTE: You needn't have two functions in service toFormGroup and toFormGroupPartTwo. If you see is the same function, you "feed" the function with different arguments, but is the same function.
In the stackblitz has the two options together
Update update code to make a break,
Solution 2
Use Top level form and wrap your child form inside the parent form and use provider to use existing Form
Parent.component.html
<form [formGroup]="form" (ngSubmit)="onClick();">
<h1>Part1</h1>
<div class="row" formArrayName="part1" *ngFor="let c of form['controls']['part1']['controls'];let i =index">
<div class="col">
<input [attr.type]="jsonDataPart1[i].type"
class="form-control" [attr.placeholder]="jsonDataPart1[i].label"
[formControlName]="i" >
</div>
</div>
<app-part2 [part2]="jsonDataPart2">
<h1>Part2</h1>
</app-part2>
<br>
<button class="btn btn-primary">Save</button>
</form>
child.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { FormGroup, FormControl, ControlContainer, FormGroupDirective, FormArray } from '@angular/forms';
@Component({
selector: 'app-part2',
templateUrl: './part2.component.html',
styleUrls: ['./part2.component.css'],
viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }]
})
export class Part2Component implements OnInit {
@Input('part2') part2;
part2Form;
constructor(private parentForm: FormGroupDirective) { }
ngOnInit() {
this.part2Form = this.parentForm.form;
const control = this.part2.map(d => new FormControl());
this.part2Form.addControl('part2F', new FormGroup({
part2: new FormArray(control)
}))
}
}
Example:https://stackblitz.com/edit/angular-xrrabj
Maniraj Murugan
Proud | 27 | Farmer | Cricketer Born and brought up from evergreen town Karur, Tamilnadu, India. Civil Engineer by graduation and Software Engineer by Profession .. If my answers helped you, feel free to buy a coffee for me You can contact me via email in [email protected] ..
Updated on June 26, 2022Comments
-
Maniraj Murugan almost 2 years
I am making angular application with angular dynamic form where i am loading data for dynamic form through JSON..
JSON has two parts such as part 1 and part 2,
jsonDataPart1: any = [ { "elementType": "textbox", "class": "col-12 col-md-4 col-sm-12", "key": "project_name", "label": "Project Name", "type": "text", "value": "", "required": false, "minlength": 3, "maxlength": 20, "order": 1 }, { "elementType": "textbox", "class": "col-12 col-md-4 col-sm-12", "key": "project_desc", "label": "Project Description", "type": "text", "value": "", "required": true, "order": 2 } ] jsonDataPart2: any = [ { "elementType": "textbox", "class": "col-12 col-md-4 col-sm-12", "key": "property_one", "label": "Property One", "type": "text", "value": "", "required": true, "order": 3 }, { "elementType": "textbox", "class": "col-12 col-md-4 col-sm-12", "key": "property_two", "label": "Property Two", "type": "text", "value": "", "required": true, "order": 4 }, { "elementType": "radio", "class": "col-12 col-md-3 col-sm-12", "key": "property_required", "label": "Property Required", "options": [ { "key": "required", "value": "Required" }, { "key": "not_required", "value": "Not Required" } ], "order": 5 }, { "elementType": "checkbox", "class": "col-12 col-md-3 col-sm-12", "key": "property_check", "label": "Property Required", "order": 6 } ]
And i am loading the JSON as separate part like,
ngOnInit() { //Building form first part this.questions = this.service.getQuestions(this.jsonDataPart1) this.form = this.qcs.toFormGroup(this.questions); //Building form second part this.questionsPartTwo = this.service.getQuestions(this.jsonDataPart2) this.formPartTwo = this.qcs.toFormGroupPartTwo(this.questionsPartTwo); }
And HTML looks like,
<div> <form (ngSubmit)="onSubmit()" [formGroup]="form"> <h4> <b> Form Part One begins from here </b> </h4> <div *ngFor="let question of questions" class="form-row"> <ng-container> <app-question [question]="question" [form]="form"></app-question> </ng-container> </div> <h4> <b> Form Part Two begins from here </b> </h4> <div *ngFor="let partTwo of questionsPartTwo"> <ng-container> <app-question [question]="partTwo" [form]="formPartTwo"></app-question> </ng-container> </div> <div class="form-row"> <button type="submit" [disabled]="!form.valid">Save</button> </div> </form> <br> <pre> {{form?.value|json}} </pre> </div>
I need to combine these two and need to get single output for the whole single form..
In my real application i am having two json data and loading each separately and assigning form so please dont break out the part one and part two json..
Let me stop the code here as its getting long you might get confused..
Here is a working stackblitz: https://stackblitz.com/edit/angular-x4a5b6-2rykpo
Just take a workaround
dynamic-form.component.ts and dynamic-form.component.html
You will get clear what i have done..Kindly help me to load the splitted JSON to
this.service.getQuestions
and get two parts and join both in final output to submit..If i am wrong in approach kindly help me to correct it as i am new in angular and dynamic form.. It needs to be in angular dynamic form and
json
loading only no change in it..Help i am expecting is from combining both parts 1 and 2 while submitting form..
Please help me i am stucking for a long to come out of it..
-
Daniel W Strimpel over 5 yearsAre you asking how to get the data in the payload together? Meaning changing this line:
this.payLoad = JSON.stringify(this.form.value);
If so, you should be able to do this to combine them together:this.payLoad = JSON.stringify({ ...this.form.value, ...this.formPartTwo.value });
-
Dale K over 5 yearsCreate a top level FormGroup, then add 2 child FormGroups, 1 for each of your JSON forms. Now you have a single form - job done.
-
-
Maniraj Murugan over 5 yearsEliseo, Thanks but i do need to have title for each part above like part 1 and part 2 for separate blocks.. Is it possible to give it when we have unique form??
-
Maniraj Murugan over 5 yearsAnd also you are correct that i can have it in unique, But to have title on each part's top (Part 1 and Part 2) only i am doing like this.. Is there any alternative approach.. Hope you can help in it..
-
Eliseo over 5 yearsSee the code update. We has a variable "questionBreak" equal the first question of the second jsonData, and ng-container with an if (stackblitz.com/edit/angular-x4a5b6-bv8j8d)
-
Maniraj Murugan over 5 yearsEliseo, can you try out without dynamic form, stackoverflow.com/questions/53538849/…