1

I'm having a bit of an issue defining an array in reactive forms model: (since reactive froms can't simply accept a model (afaik) and work by it, I need to manually define it):

Stackblitz

Object from Backend:

  {
    propOne: 'X',
    propTwo: 'Y',
    propArray: [
      {
        objPropA: 'a',
        objPropB: 'b'
      },
      {
        objPropA: 'c',
        objPropB: 'd'
      },
            {
        objPropA: 'e',
        objPropB: 'f'
      }
    ]
  }

Component:

 ngOnInit() {
    this.myForm = this.fb.group({
      propOne: '',
      propTwo: '',
      propArray: this.fb.array([this.createItem(), this.createItem(), this.createItem()])
    });

    // apply the value to the form
    this.myForm.setValue(this.valueFromBackend);
  }

  private createItem(): FormGroup {
    return this.fb.group({
      objPropA: '',
      objPropB: '',
    });
  }

I would like to avoid creating a form group for each element i'm expecting (this.createItem() x ElementsCount) when defining the form.

Am I really required to define how many elements i'm expecting in the my array?

Am I doing it wrong ?

3
  • You might want to look into dynamic forms: angular.io/guide/dynamic-form Commented Sep 26, 2019 at 9:32
  • I've already created a form for different purpose. What you expect is in stackblitz.com/edit/add-rows-dynamically-formgroup-formarray Commented Sep 26, 2019 at 9:35
  • You can write some code to determine the number of form groups you want in your form array and then you can push your form groups instead of writing them manually. Commented Sep 26, 2019 at 9:35

3 Answers 3

4

Here is one approach you can take. You can loop through the propArray (Backend response item) and then push the values to an array. After that you can use that freshly created array to create a FormArray out of it.

  ngOnInit() {
    this.myForm = this.fb.group({
      propOne: '',
      propTwo: '',
      propArray: this.fb.array
    });

    // dynamically set value
    this.myForm.setValue(this.valueFromBackend);
    let propertyArray: any = [];
    for(let item of this.valueFromBackend.propArray) {
      propertyArray.push(this.createItem(item));
    }
    this.myForm.controls['propArray'] = this.fb.array(propertyArray);
    // log the form
    console.log(this.myForm.controls['propArray']);
  }

  private createItem(item): FormGroup {
    return this.fb.group({
      objPropA: item.objPropA,
      objPropB: item.objPropB,
    });
  }
}

Stackblitz

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks. might as well createItemS(count): FormGroup[] helper method that accepts a count constructs an array and on my model creation: fb.array([ ...createItems(propCount) ]) but this still feels hacky. I'm not trying to beautify the duplicates, im trying to avoid them. if possible.
For a real example - see populateForm()
Post a whole code. Where do you use this part fb.array([ ...createItems(propCount) ])?
You need some kind of a loop there. Whether in a way I did it, or in a way you did it in this new link. It's definitely not a hacky way.
0

Try this, Once you get your data from backend in your component.ts:

formArrayLength: number;
propArray;

ngOnInit() {
this.myForm = this.fb.group({
      propOne: '',
      propTwo: '',
      propArray: this.fb.array([this.createItem()])
    });
this.formArrayLength = yourObject.propArray.length;
this.addFormGroups();
}
addFormGroups() {
this.propArray = this.myForm.get('propArray') as FormArray;
for(let i=0;i<this.formArrayLength ;i++) {
  this.propArray.push(this.createItem());
}

}

Comments

0

This Will Help You

   ngOnInit() {
        this.myForm = this.fb.group({
          propOne: '',
          propTwo: '',
          propArray: this.fb.array([this.createItem()])
        });

        // apply the value to the form
        this.myForm.setValue(this.valueFromBackend);
    this.myForm.controls['propOne'].setValue(this.valueFromBackend.propOne);
    this.myForm.controls['propTwo'].setValue(this.valueFromBackend.propTwo);
      let count = 0;
      const propArrayLength: number = this.valueFromBackend.propArray.length;
      if (propArrayLength > 0) {
        for (count = 0; count < this.valueFromBackend.propArray.; count++) {

            (<FormArray>this.myForm.controls['propArray']).at(count).get('objPropA')
            .setValue(this.valueFromBackend.propArray[count].objPropA);
            (<FormArray>this.myForm.controls['propArray']).at(count).get('objPropB')
            .setValue(this.valueFromBackend.propArray[count].objPropB);

            this.createItem();
      }
    }
      private createItem(): FormGroup {
        return this.fb.group({
          objPropA:[''],
          objPropB: [''],
        });
      }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.