6

I want to set value in array like this:

this.form.controls[name].setValue('name')

but I am working with array forms, and this is not working, even if I pass an array index explicitly

for example, this is my form array and I want to do is to set value in a function

user: FormGroup;
users: FormGroup;

constructor(private fb: FormBuilder) {}
ngOnInit() {
  this.user = this.buildGroup();
  this.users = this.fb.group({
    data: this.fb.array([this.user])
  });
}
get fData() {
  return this.users.get('data') as FormArray;
}
buildGroup() {
  return this.fb.group({
    name: ['', [Validators.required, Validators.minLength(2)]],
    account: this.fb.group({
      email: ['', Validators.required],
      confirm: ['', Validators.required]
    })
  });
}
setValue(index) {
  // This doesn't work
  this.fData[index].controls[name].setValue('name')
}
onSubmit() {
  this.fData.push(this.buildGroup());
  const {valid, value} = this.fData;
  console.log(valid, value);
}
BinaryButterfly
  • 18,137
  • 13
  • 50
  • 91
LLaza
  • 369
  • 2
  • 5
  • 13
  • Scrap my previous answer. The problem is most likely that you are not [passing an array to setValue](https://angular.io/api/forms/FormArray#example-1). – Tom Jul 08 '17 at 15:14
  • Should not to pass the index, to the specific array form? I am tryng this but this is not working setValue(index) { this.fData.setValue(['Name']); } The error says that must supply a value for fom control with name 'name' – LLaza Jul 08 '17 at 15:33
  • Try this: `this.fData[index].controls['name'].setValue(['name'])` – Tom Jul 08 '17 at 15:54
  • not working: Cannot read property 'controls' of undefined – LLaza Jul 08 '17 at 16:08

3 Answers3

30

For arrays, you need to use setControl. Something like this:

    this.productForm = this.fb.group({
        productName: ['', [Validators.required,
                           Validators.minLength(3),
                           Validators.maxLength(50)]],
        productCode: ['', Validators.required],
        starRating: ['', NumberValidators.range(1, 5)],
        tags: this.fb.array([]),
        description: ''
    });

    ...

    // Update the data on the form
    this.productForm.patchValue({
        productName: this.product.productName,
        productCode: this.product.productCode,
        starRating: this.product.starRating,
        description: this.product.description
    });
    this.productForm.setControl('tags', this.fb.array(this.product.tags || []));
DeborahK
  • 57,520
  • 12
  • 104
  • 129
  • 4
    I must have missed that in your pluralsight course ;-) – Tom Jul 08 '17 at 16:16
  • 1
    Found it: https://app.pluralsight.com/player?course=angular-2-reactive-forms&author=deborah-kurata&name=angular-2-reactive-forms-m8&clip=5&mode=live&start=348.941 – Tom Jul 08 '17 at 16:24
  • 2
    The "Angular: Reactive Forms" course? Hope it was helpful! – DeborahK Jul 08 '17 at 16:25
  • 1
    LOL! Wish we could add emojis to comments! – DeborahK Jul 08 '17 at 16:26
  • How can I loop through this array in the html? – codejunkie Nov 09 '17 at 17:05
  • it's also right here https://angular.io/guide/reactive-forms just search "setControl" – nescafe Apr 06 '18 at 14:57
  • @DeborahK How can we add few formGroups to formArray like this? If our `template` has `[formGroupName]="index"` other than `[formControlName]="index"` this approach gives this error "ERROR Error: Cannot find control with path: 'addresses -> 0 -> addressType'". any suggestions? – Sanira Nimantha Jul 03 '19 at 09:14
  • 1
    Thank you so much!!!! I was using control.push() but control.setControl() was exactly what I needed!! – Tyron Aug 31 '19 at 06:23
8

Here is what I have done to set value manually in formArray's specific form control and worked for me. I have formArray named as bundleDetails.

   this.formBuilderObj['bundleDetails'] = 
   this.formBuilder.array([this.createBundleItem()]);

    createBundleItem(): FormGroup {
    return this.formBuilder.group({
     bsku: ['', Validators.required],
     bqty: ['', Validators.required],
     bprice: ['', Validators.required]
    });
   }

Method to set bsku control's value (where index is [formGroupName]="i" passed from html file).

   setSku(sku: string, index: number) {
   const faControl = 
   (<FormArray>this.pmForm.controls['bundleDetails']).at(index);
   faControl['controls'].bsku.setValue(sku);
  }

Hope this helps. Happy coding.

Krisztián Balla
  • 19,223
  • 13
  • 68
  • 84
Nirali
  • 454
  • 1
  • 6
  • 16
  • 2
    Excellent, this works great and I believe answers the question of setting the value of a control at specific index, and not the value of the whole array... – Alfa Bravo Feb 23 '19 at 07:22
0

If you're getting the error "ERROR Error: Cannot find control with path: 'addresses -> 0 -> addressType'" or something similar, it's most likely cause you're passing the values in but your html template is expecting values along with a control name.

To resolve this, iterate over each item in your array, and create a new form group instance for each value - based on what your view is expecting - then push to a new array variable, which we then set in our form.

See code below:

var tagsArray = [];
this.product.tags.forEach(product => tagsArray.push(this.fb.group({tag: [product.tag, [Validators.required]]})));
this.productForm.setControl('tags', this.fb.array(tagsArray || []));

Referenced in view like so:

<div class="tag" *ngFor="let t of tags.controls; let i = index" [formGroupName]="i" class="mb-2">
      <input type="text" formControlName="tag" placeholder="Tag name" class="primary_input">
       <button mat-icon-button (click)="deleteTag(i)">
           <mat-icon>clear</mat-icon>
       </button>
 </div>

This lets you load previous results while enabling the ability to add more values and validate user input.

Hope this helps.