How to combine two parts of single form in angular?

11,570

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

Share:
11,570
Maniraj Murugan
Author by

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, 2022

Comments

  • Maniraj Murugan
    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
      Daniel W Strimpel over 5 years
      Are 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
      Dale K over 5 years
      Create 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
    Maniraj Murugan over 5 years
    Eliseo, 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
    Maniraj Murugan over 5 years
    And 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
    Eliseo over 5 years
    See 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
    Maniraj Murugan over 5 years
    Eliseo, can you try out without dynamic form, stackoverflow.com/questions/53538849/…