user1675891
user1675891

Reputation:

How to use ReactiveFormsModule and validations for dynamically added controls in Angular?

I have a couple of fields connected to the FormBuilder like this.

constructor(private builder: FormBuilder) {
  this.form = builder.group({
    "firstName": [...],
    "lastName": [...]
  });
}

In the markup, besides the fix controls, I'll also have an unknown number of input boxes. It's starting with zero and can be increased, as the user clicks on a button, which adds a new input box by each click. There'll be also a removal button for each input box so the number of those is fully dynamic.

<div class="input-caption">FirstName</div>
<input type="text" formControlName="firstName">

<div class="input-caption">LastName</div>
<input type="text" formControlName="lastName">

<div id="options"></div>
<button (click)="addOption()">Add option</button>

As the dynamically added fields need to be validated, I feel that I need to declare them in the group definition. I have no idea how, though.

When I googled, I got a bunch of hits on [(ngModel)] but I also read that it's supposed to be used with the FormsModule and not ReactiveFormsModule as discussed in a blog.

How should I approach it? Is double-bound ngModel the only option?

Edit based on the answer.

HTML

<div *ngFor="let tag of []; let i = index;" [formGroupName]="i">
  <div class="input-caption">Tag</div>
  <input formControlName="name"> -->
</div>

TS

constructor(private builder: FormBuilder) {
  this.form = builder.group({
    "firstName": [...],
    "lastName": [...],
    "tags": this.builder.array([]),
  });
}

addTag(): void {
  (this.form.controls.tags as FormArray).???;
}

I've also tried to specify a hard-coded array in the markup as follows but didn't get to see any controls being rendered.

<div *ngFor="let tag of [{'name':'uno'},{'name':'duo'}]; let i = index;" 
     [formGroupName]="i">
  <div class="input-caption">Tag</div>
  <input formControlName="name"> -->
</div>

Upvotes: 1

Views: 333

Answers (2)

DeborahK
DeborahK

Reputation: 60518

If you just want this code to work, you just need to change it to an array:

<div *ngFor="let tag of ['uno','duo']; let i = index;" 
     [formGroupName]="i">
  <div class="input-caption">{{ tag }}</div>
  <input formControlName="name"> -->
</div>

And they don't really need to be form groups. It would probably be simpler if they aren't:

<div *ngFor="let tag of ['uno','duo']">
  <div class="input-caption">{{ tag }}</div>
  <input [formControlName]="tag"> -->
</div>

And if this is all you need ... then you don't really even need FormArrays.

Upvotes: 0

DeborahK
DeborahK

Reputation: 60518

Your scenario is the purpose of a FormArray. See the docs here: https://angular.io/guide/reactive-forms#use-formarray-to-present-an-array-of-formgroups

The docs show an array of FormGroups, but you can also use it to create an array of FormControls.

Here is an example from my application:

    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: ''
    });

My "tags" look like this:

enter image description here

I set default values into these controls like this:

    // 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 || []));

You can find my sample code here: https://github.com/DeborahK/Angular2-ReactiveForms In the "APM" or "APM - Updated" folders.

This is the code from the Pluralsight course: Angular Reactive Forms here: https://app.pluralsight.com/library/courses/angular-2-reactive-forms/table-of-contents

Upvotes: 2

Related Questions