Search code examples
angularangular-reactive-formsangular2-formbuilder

Angular Reactive Form nested Form


I created a nested form, but the strange thing is that the parameters key inside the dummy data json consists of 2 objects and inside actual form value there is only one object inside the form array.

I am not able to find any error. I don't know what is going on or what causing this to happen.

export class App implements OnInit {
  name = 'Angular';
  my_json = {
    machine: {
      idMachine: 'YyWTceUNqsonOvO2ZOLP',
      note: 'accesso con 7u89',
      parameters: [
        {
          description: 'Pompa aria',
          factoryValue: '1676',
          parameter: '7',
        },
        {
          description: 'Cattura ',
          factoryValue: '6589',
          parameter: '5',
        },
      ],
      model: 'AREA',
      serie: 'UIXX7',
      machine: 'T7UID',
    },
    address: 'Via Italia 42',
    phone: '+393295000000',
    email: 'callme@gmail.com',
    name: 'Pippo',
    surname: 'Master',
    idUser: 'tt0QAHRD9JFuMETnLvjh',
  };
  public formClient!: FormGroup;

  constructor(public formBuilder: FormBuilder) {
    this.formClient = this.formBuilder.group({
      name: ['', Validators.required],
      surname: ['', Validators.required],
      address: ['', Validators.required],
      email: ['', Validators.required],
      phone: ['', Validators.required],
      machine: this.formBuilder.group({
        serie: [''],
        machine: [''],
        note: [''],
        model: [''],
        idMachine: [''],
        parameters: this.formBuilder.array([
          this.formBuilder.group({
            description: [''],
            factoryValue: [''],
            parameter: [''],
          }),
        ]),
      }),
    });
  }

  ngOnInit() {
    console.log('my data ', this.my_json);
    this.formClient.patchValue(this.my_json);
    console.log('my form values ', this.formClient.value);
  }
}

Thank you.


Solution

  • .patchValue() doesn't create the FormGroup/FormControl instances for a FormArray.

    Instead, you need to map your parameters objects when assigning the value of the form.

    You also don't want to be doing that work in the constructor. This should go into a lifecycle method such as OnInit().

    Untyped FormGroup example:

      form!: FormGroup;
    
      initParameterForm(parameter?: IParameter): FormGroup {
        return new FormGroup({
          description: new FormControl(parameter?.description || null),
          factoryValue: new FormControl(parameter?.factoryValue || null),
          parameter: new FormControl(parameter?.parameter || null),
        });
      }
    
      initMachineForm(machine?: IMachine): FormGroup {
        // other fields here
        
        parameters: new FormArray(machine?.parameters?.map(parameter => initParameterForm(parameter) || []),
      }
    
      ngOnInit(): void {
        // other code to get machine, if applicable
        this.form = this.initMachineForm(machine);
      }
    

    I would highly recommend providing strongly typed forms if you're using Angular 15.