7

I would like to create an editable table with FormArray.

For this, I have the results attribute that is rendered in the table.

What's the proper way to initialize it with FormArray data?

results: Array;
tableForm: FormGroup;

ngOnInit(private fb: FormBuilder) {
  this.tableForm = this.fb.group({
    arrayForm: this.fb.array([])
  });
}
10
  • not sure, but if you're referring to the idea of creating a reactive form based on an existing interface. it's not possible yet. Commented Sep 27, 2019 at 9:59
  • @Stavm yes it is, but it's not what's asked. Commented Sep 27, 2019 at 10:00
  • No, I wanna initiate formarray from existing array. 'results' is an array, I wanna put all the date to a FormArray. Commented Sep 27, 2019 at 10:01
  • @Maryannah i'd love a reference . Commented Sep 27, 2019 at 10:02
  • @Liem you can check this: alligator.io/angular/reactive-forms-formarray-dynamic-fields it explains it quite well Commented Sep 27, 2019 at 10:02

2 Answers 2

11

A form array is a bundle of form controls (as a reminder, a form group is a form control).

In the following I will assume your results are model-related, such as

[
  { id: 1, title: 'title 1' },
  { id: 2, title: 'title 2' },
]

(If not, feel free to explain to me what the results are)

Since a form array must accept controls, you will have to map your results to comply with the signature.

You can do it with this :

ngOnInit(private fb: FormBuilder) {
 this.tableForm = this.fb.group({
   arrayForm: this.fb.array(this.results.map(r => this.fb.group(r)))
 });
}

With this, your form array will contain a form group, made of all the properties in your object.

Is this what you wanted or not ?

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

1 Comment

why are you passing the FormBuilder as a parameter on the ngOnInit instead of injecting it in the constructor?
4

You can create an array based on the OBJECT(not an interface).

I actually wrote a small demo a few days ago:

our OBJECT (!):

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

Component:

ngOnInit() {
    const count = this.valueFromBackend.propArray.length

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

    // dynamically set value
    this.myForm.setValue(this.valueFromBackend);
  }

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

  private createItems(count: number): FormGroup[] {
    const arr = [];
    for (let i = 0; i < count; i++) {
      arr.push(this.createItem());
    }
    return arr;
  }

HTML:

<form [formGroup]="myForm">
    <div formArrayName="propArray" *ngFor="let item of myForm.get('propArray').controls; let i = index;">
        <div [formGroupName]="i">
            <input formControlName="objPropA" placeholder="Item name">
      <input formControlName="objPropB" placeholder="Item description">
  </div>
  </div>
</form>

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.