How to get the value for Control inside FormArray in Angular while displaying record for patchValue operation

Viewed 6048

I've been using FormArray in angular reactive form, and everything works just fine until I try to do patchValue() operation.

Here, I try to edit projectForm. In the form you can add multiple developers from <select> <option> </option> </select>. Value in the option field are from the database and the user can add any numbers of developers as he/she wants.

Simplified Code version of the problem is as below:
project.component.ts

projectForm: FormGroup

constructor(private fb: FormBuilder, private projectService: ProjectService, private developerService: DeveloperService){ }

ngOnInit() {
    this.developerService.getDeveloper().subscribe((data) => {
        this.developers = data;
    }, (error) => {
        console.log(error)
    } 
    });

    this.projectForm = this.fb.group({
        project_name: [''],
        devs: this.fb.array([this.buildDevs()]),
    })
    this.editProject();
}

buildDevs(): FormGroup {
    return this.fb.group({
      developer: ['', Validators.required]
    });
  }

displayProject(id: number) {
    this.projectService.getProjectDetail(id).subscribe(
        (project) => this.editProject(project),
        (error) => console.log(error)
    )
}

editProject(project){
    this.projectForm.patchValue({
       project_name: project.project_name, 
    });
    this.projectForm.setControl('devs', this.fb.array(project.developer || []));
}

ProjectService is responding with correct project response. Nothing wrong in there.
Add and update post need to be done in same form, and adding the form is working fine. `project.component.html'

<form [formGroup]="projectForm">

    <label>Name: </label>
    <input type="text" formControlName="project_name">

    <label> Developers: </label>
    <div formArrayName="devs">
        <div *ngFor="let d of projectForm.controls.devs.controls; let i = index" [formGroupName]="i">
             <select formControlName="developer" *ngIf="developers">
               <option *ngFor="let dev of developers" value="{{ dev.id }}">{{ dev.user.username }}
               </option> 
             </select>   
        </div>
    </div>
</form>

Following error in the console is present in the response whenever I visit the project edit route
 error seen in the console
The option field number are exact with the number of developers associated with the project want to be edited but the username of the developer is not seen in the option.
ERROR Error: Cannot find control with path: 'devs -> 0 -> developer'
ERROR Error: Cannot find control with path: 'devs -> 1 -> developer' so on ... as the number of developer ...
Any help will be appreciated as I am new to angular and tried all possible options that I can do. Thank you.

2 Answers

I have used patchModelValue method of @rxweb/reactive-form-validators, it will update the value of the FormControl inside the FormGroup based on provided server JSON object or model object. It will update the particular FormControl's value from the FormGroup. You can pass the project.developer during your edit project api call.

export class UserComponent implements OnInit {
    userInfoFormGroup: RxFormGroup

    constructor(
        private formBuilder: RxFormBuilder    ) { }

    ngOnInit() {
      this.userInfoFormGroup = <RxFormGroup>this.formBuilder.group({      
          devs:[
          {
            developer:['',Validators.required]
          }]
        });
    }
 getFormArray(){
      let formarray = this.userInfoFormGroup.controls.devs as FormArray;
      return formarray.controls;
    }

    editProject()
    {
          this.userInfoFormGroup.patchModelValue( {
                devs: [{ developer: "John" }] });
    }
}

You just need to import RxFormBuilder in your component and RxReactiveFormsModule in your app module ts

Please refer this working example

you need to initialize FormArray with required number of controls before using patchValue.

assuming project.developer is an Array of Objects in this form based on your code

[{developer: "dev1"},{developer: "dev2"},{developer: "dev3"}]
  editProject(project) {
    const devs = this.projectForm.get("devs") as FormArray;
    devs.clear();
    project.developer.forEach(d => devs.push(this.buildDevs()));
    this.projectForm.patchValue({
      project_name: project.project_name,
      devs: project.developer
    });
  }
Related