Search code examples
angulartypescriptangular-reactive-formsangular-formbuilder

How to patch select box value inside nested reactive forms in angular?


User class is as below:

export class User {
 name: string
 details: Details;
}

Details class is as below:

export class Details {
country: Country;
major : Major;
}

Major class is as below:

export class Major{
department : string;
subject : Subject;
}

I have created form as below:

   userForm : FormGroup;
    
   constructor(private fb: FormBuilder){}

   ngOnInit(): void {
    this.createUserForm();
  }
  
  
  createUserForm() {
    this.userForm = this.fb.group(
      {
        name:new FormControl(null, Validators.required),
        details: this.fb.array([this.createDetailsForm()])
      }
    );
  }

  createDetailsForm(): FormGroup {
     return this.fb.group({
      country:this.createCountryForm(), 
      major:this.fb.array([this.createMajorForm()])
    })
  }


  createCountryForm(): FormGroup {
    return this.fb.group({
      id: new FormControl(null)
    })
  }

  createMajorForm(): FormGroup {
    return this.fb.group({
      department:new FormControl(null),
      subject: this.createSubjectForm()
    });
  }
  
  
    createSubjectForm(): FormGroup {
    return this.fb.group({
      id: new FormControl(null)
    })
  }

Below is my JSON to create user in server side:

 {
    "name": "Kevin",
    "details": [{
        "country": {
            "id": 1 //used in select box. It is not getting patched from user form.(problem area)
        },
        "major": [{
            "department": "Science",
            "subject": {
                "id": 2 //used in select box. It is not getting patched from user form. (problem area)
            }
        }]
    }]
  }

Country is class as below:

export class Country{
    id: number;
    name: string;
}

Country will have data as below:

 countries : Country [] = [
    {id:1, name:"Serbia"},
    {id:2, name:"Slovenia"},
    {id:3,name:"India"}
    ]

Html part for country is as below:

<div [formGroupName]="country">
                            <select>
                              <option
                                *ngFor="let c of countries"
                                [Value]="c.id"
                              >
                                {{ c.name }}
                              </option>
                            </select>
                          </div>

Subject is class as below:

export class Subject{
  id:number;
  name:string;
}

Subject will be populated from server as below:

   subjects : Subject [] = [
    {id:1, name:"Chemistry"},
    {id:2, name:"Physics"},
    {id:3, name:"Botany"}
    ]

Html part of subject is as below:

  <div [formGroupName]="subject">
                                <select>
                                  <option
                                    *ngFor="let s of subjects"
                                    [Value]="s.id"
                                  >
                                    {{ s.name }}
                                  </option>
                                </select>
                              </div>

Problem Explanation: It is a user details form. It consists of form arrays and form groups in nested form. I am able to populate both subject and country in my select box area. But I am not able to patch or set value for id for both subject and country in my user form.

Right now I am using this for patching my user form:

this.service.registerUser(this.userForm.value);

So what is the proper way of patching select box value? Is there anything wrong I am doing in ts part or in html part? Or is there anything I need to do extra to set id value from both subject and country select box in user form? And how to set controls inside select box ? Do I have to patch select box value independently ? I will also use this form for edit functionality as well just in case if it makes any difference for patching or setting value. Any kind of suggestion or solution is highly appreciated. Thanks in advance.


Solution

    1. You haven’t set formControlName on any of your HTML controls so your template is not bound to the form model.
    2. You shouldn’t use[] around formGroupName as you are binding to a string value rather than a variable.

    You need something like:

    <div formGroupName="country">
       <select formControlName=“id”>
       …
    

    To patch the value you can use:

    this.userForm.get(‘country.id’).patchValue(123);