I am currently working on a project where I have a reactive form array
which will be displayed on the template using an *ngIf
. I think that's the normal use case and nothing special. But now I build this like
<div *ngFor="let control of form.controls['someArray'].value; let index = index">
[...]
<button mat-flat-button color="warn">Delete</button>
</div>
<button mat-flat-button color="primary">Add</button>
The Delete
button does not react to my clicks, but the Add
button does. For some reason when I remove the let index = index
it works again or if I put the button outside of this *ngFor
.
I hope you can help me. Thank you very much. Couldn't find any solution so far.
Example: https://stackblitz.com/edit/angular-form-array-example-hq5tud
import { Component } from '@angular/core';
import { FormControl, FormGroup, FormArray, FormBuilder } from '@angular/forms';
@Component({
selector: 'my-app',
template: `
<form [formGroup]="form">
<input type="checkbox" formControlName="published"> Published
<div *ngIf="form.controls.published.value">
<h2>Credentials</h2>
<button (click)="addCreds()">Add</button>
<div formArrayName="credentials" *ngFor="let creds of form.controls.credentials?.value; let i = index">
<ng-container [formGroupName]="i">
<input placeholder="Username" formControlName="username">
<input placeholder="Password" formControlName="password">
<button mat-flat-button (click)="buttonClick()"> Test inside </button>
</ng-container>
</div>
<button mat-flat-button (click)="buttonClick()"> Test outside </button>
</div>
</form>
`,
})
export class AppComponent {
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = this.fb.group({
published: true,
credentials: this.fb.array([]),
});
}
addCreds() {
const creds = this.form.controls.credentials as FormArray;
creds.push(this.fb.group({
username: '',
password: '',
}));
}
buttonClick() {
console.log('Clicked');
}
}
Here is the working example Please check the link
https://stackblitz.com/edit/angular-form-array-example-test123-2jzdij
Finally I found the solution with the help of @ashot-aleqsanyan . The reason for that is still unclear. If anyone has an explanation for this bahavior then please tell us about.
The solution:
Replace the form.controls.credentials?.value
to form.get('credentials').controls
in the .html template does the trick. After that the mat-buttons are working inside the *ngFor
again.
import { Component } from '@angular/core';
import { FormControl, FormGroup, FormArray, FormBuilder } from '@angular/forms';
@Component({
selector: 'my-app',
template: `
<form [formGroup]="form">
<input type="checkbox" formControlName="published"> Published
<div *ngIf="form.controls.published.value">
<h2>Credentials</h2>
<button (click)="addCreds()">Add</button>
<div formArrayName="credentials" *ngFor="let creds of form.get('credentials').controls; let i = index">
<ng-container [formGroupName]="i">
<input placeholder="Username" formControlName="username">
<input placeholder="Password" formControlName="password">
<button mat-flat-button (click)="buttonClick()"> Test inside </button>
</ng-container>
</div>
<button mat-flat-button (click)="buttonClick()"> Test outside </button>
</div>
</form>
`,
})
export class AppComponent {
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = this.fb.group({
published: true,
credentials: this.fb.array([]),
});
}
addCreds() {
const creds = this.form.controls.credentials as FormArray;
creds.push(this.fb.group({
username: '',
password: '',
}));
}
buttonClick() {
console.log('Clicked');
}
}
I don't know why, but like you say the (click) event is not being trigger inside the <ng-container [formGroupName]="i">
when you use the directives mat-flat-button
inside the button <button mat-flat-button> Test outside </button>
If you remove the mat-flat-button
it works:
<button (click)="myFunc()"> Test outside </button>
Here is the code that I test with https://stackblitz.com/edit/angular-form-array-example-hq5tud :
app.component.ts :
import { Component } from '@angular/core';
import { FormControl, FormGroup, FormArray, FormBuilder } from '@angular/forms';
@Component({
selector: 'my-app',
template: `
<form [formGroup]="form">
<input type="checkbox" formControlName="published"> Published
<div *ngIf="form.controls.published.value">
<h2>Credentials</h2>
<button (click)="addCreds()">Add</button>
<div formArrayName="credentials" *ngFor="let creds of form.controls.credentials?.value; let i = index">
<ng-container [formGroupName]="i">
<input placeholder="Username" formControlName="username">
<input placeholder="Password" formControlName="password">
<button class="mat-flat-button" (click)="testFunc()"> Test inside </button>
</ng-container>
</div>
<button mat-flat-button (click)="testFunc()"> Test outside </button>
</div>
</form>
`,
})
export class AppComponent {
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = this.fb.group({
published: true,
credentials: this.fb.array([]),
});
}
addCreds() {
const creds = this.form.controls.credentials as FormArray;
creds.push(this.fb.group({
username: '',
password: '',
}));
}
testFunc() {
console.log('hello');
}
}