TLDR: How to use FormArray or FormGroup with multiple file-input fields?
Hello everyone,
I want to build an event manager with Angular. Each event has a title, description, image and a flyer. The image is a png or jpg file-input and the flyer is a pdf one.
I need a toolbar performing the following actions:
- add should append a new event to the list withouth image or pdf
- delete should remove all selected event
- save should update to the database the event and load the two file-inputs files.
The list of event look like:
But I struggle to implement the form.
How can I use multiple file-input into a dynamic form with angular?
This is what I tried to do (event = promotion):
HTML:
<form [formGroup]="promotionForm" *ngFor="let promotion of promotions; let i = index;">
<div class="card" *ngIf="promotion.displayed" (click)="promotion.selected = !promotion.selected;">
<div>
<h2>Title</h2>
<input matInput [(ngModel)]="promotion.title" [ngModelOptions]="{standalone: true}"/>
</div>
<div>
<h2>Subtitle</h2>
<input matInput [(ngModel)]="promotion.subtitle" [ngModelOptions]="{standalone: true}"/>
</div>
<div>
<h2>Language</h2>
<mat-select [(value)]="promotion.language"></mat-select>
</div>
<div class="description">
<h2>Description</h2>
<textarea matInput cdkAutosizeMinRows="5" [(ngModel)]="promotion.description"></textarea>
</div>
<div class="img">
<div class="container">
<h2>Image</h2>
<mat-form-field>
<ngx-mat-file-input formControlName="image" [multiple]="false" accept="image/webp, image/jpeg, image/png">
<mat-icon ngxMatFileInputIcon>folder</mat-icon>
</ngx-mat-file-input>
</mat-form-field>
</div>
<img src="{{promotion.image}}">
</div>
<div class="pdf">
<h2>PDF</h2>
<mat-form-field>
<ngx-mat-file-input formControlName="pdf" [multiple]="false" accept="application/pdf">
<mat-icon ngxMatFileInputIcon>folder</mat-icon>
</ngx-mat-file-input>
</mat-form-field>
</div>
<mat-checkbox class="checkbox" [checked]="promotion.selected"></mat-checkbox>
</div>
</form>
TS:
promotions: Promotion[] = [];
maxSize: number = 2; //Mo
promotionForm: FormGroup;
images: any[];
pdfs: any[];
constructor(private promotionService: PromotionService, private fb: FormBuilder) { }
ngOnInit(): void {
this.promotionForm = this.fb.group({
image: [MaxSizeValidator(this.maxSize * 1024 * 1024)],
pdf: [MaxSizeValidator(this.maxSize * 1024 * 1024)]
})
this.getAllPromotions();
}
getAllPromotions() {
this.promotionService.getAllPromotions()
.subscribe(promotions => {
this.promotions = promotions.reverse();
this.promotions.map(p => {
p.selected = false;
p.displayed = true;
})
})
}
deletePromotions() {
let toDelete$ = this.promotions.filter(p => p.selected).map(p => { return this.promotionService.deletePromotion(p._id) });
forkJoin(toDelete$).subscribe(() => this.getAllPromotions());
}
updatePromotions() {
let toUpdate$ = this.promotions.filter(p => p.selected).map(p => { return this.promotionService.updatePromotion(p) });
forkJoin(toUpdate$).subscribe(() => this.getAllPromotions());
}
selectAll() {
if (this.promotions.filter(p => p.displayed).every(p => p.selected)) {
this.promotions.map(p => p.selected = false)
} else {
this.promotions.filter(p => p.displayed).map(p => p.selected = true)
}
}
The issue with this solution is to get a unique file for each event. I want an unique file-input for each event and if I use FormGroup, I'm unable to have n file-input associated to each event. Should I use FormArrays of FormGroup and use image and pdf into each group?

