Hello, Everone. I've been trying to Upload above(image) use case. I know it is very easy when we have a single file. but now the scenario is different it consists of an array of objects with the file. Now my question is how can I render the formdata object with the array of objects where each object consists of a file. For dynamic form, I used angular reactive forms. Can anyone please suggest me how can send whole data to the backed with the single click on save button. For backend I used Springmvc. Thanks in advance.
FullSource code availabe on my Github : Source
multi-files-upload.component.html
<div class="container-fluid">
<section class="content">
<div id="main-form-content">
<form [formGroup]="documentGrp" (ngSubmit)="OnSubmit(documentGrp.value)" #uploadDocumentsForm="ngForm" ngNativeValidate>
<div class="box box-solid box-primary">
<div class="box-body" formArrayName="items">
<h2 class="page-header text-blue ">
<i class="fa fa-files-o"></i> Upload Documents
</h2>
<div class="row">
<div class="col-sm-12">
<div *ngFor="let item of items.controls; let i = index;">
<div [formGroupName]="i">
<table id="tbl-upload" class="table table-bordered">
<tbody>
<tr *ngIf="i==0" class="active">
<th>Document Name</th>
<th>Document Description</th>
<th>Document File</th>
<th> </th>
</tr>
<tr>
<td>
<div class="form-group required">
<input type="text" class="form-control" name="doc_name" formControlName="doc_name" placeholder="Enter document Category"
required="">
<div class="help-block"></div>
</div>
</td>
<td>
<div class="form-group ">
<input type="text" class="form-control" name="doc_description" formControlName="doc_description" maxlength="100" placeholder="Enter document related descriptions"
required="">
<div class="help-block"></div>
</div>
</td>
<td>
<div class="form-group required">
<input type="file" name="admission_docs_path" title="Browse Document" (change)="fileSelectionEvent($event)" required="">
<div class="help-block"></div>
</div>
</td>
<td class="remove" *ngIf=" i!=0 ">
<a title="Remove" (click)="removeItem(i)" class="fa fa-minus-square fa-lg text-red"></a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="pull-right">
<a class="btn btn-sm btn-success" title="Add More" style="" (click)="addItem()">
<i class="fa fa-plus-square"></i> Add More</a>
</div>
</div>
<!--./col-->
</div>
<!--./row-->
</div>
<!--./box-body-->
<div class="box-footer" style="align-content: center">
<button type="submit" class="btn btn-primary pull-right">Save</button>
</div>
</div>
</form>
</div>
</section>
</div>
multi-files-upload.component.ts
import { Component, OnInit, Renderer } from '@angular/core';
import { FormBuilder, FormGroup, Validators, FormArray, FormControl, NgForm } from '@angular/forms';
import { MultifilesService } from './multifiles.service'
@Component({
selector: 'app-multi-files-upload',
templateUrl: './multi-files-upload.component.html',
styleUrls: ['./multi-files-upload.component.css']
})
export class MultiFilesUploadComponent implements OnInit {
constructor(private renderer: Renderer,
private formBuilder: FormBuilder,
private multifilesService: MultifilesService
) { }
public documentGrp: FormGroup;
ngOnInit() {
this.documentGrp = this.formBuilder.group({
doc_name: '',
doc_description: '',
documentFile: File,
items: this.formBuilder.array([this.createUploadDocuments()])
});
}
public doc_name = "";
public doc_description = "";
public documentFile: File;
createUploadDocuments(): FormGroup {
return this.formBuilder.group({
doc_name: '',
doc_description: '',
documentFile: File,
});
}
get items(): FormArray {
return this.documentGrp.get('items') as FormArray;
};
addItem(): void {
this.items.insert(0, this.createUploadDocuments())
}
removeItem(index: number) {
this.items.removeAt(index);
}
public fileSelectionEvent(fileInput: any) {
if (fileInput.target.files && fileInput.target.files[0]) {
var reader = new FileReader();
reader.onload = (event: any) => {
}
this.documentFile = (fileInput.target.files[0]);
console.log("the document is" + JSON.stringify(fileInput.target.files[0].name));
reader.readAsDataURL(fileInput.target.files[0]);
}
}
public OnSubmit(formValue: any) {
let total_form: FormData[] = [];
console.log(formValue.items)
formValue.items.forEach(element => {
let upl_fom: FormData = new FormData();
console.log("each element is", element);
upl_fom.append('document_category', element.doc_name);
upl_fom.append('document_details', element.doc_description);
upl_fom.append('document_file', element.documentFile);
total_form.push(upl_fom);
});
this.multifilesService.saveFiles(total_form).subscribe(data => {
console.log("result is ", data)
})
}
}
Multifiles.service.ts
import { Injectable } from '@angular/core';
import { HttpClient,HttpHeaders } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class MultifilesService {
constructor( private http: HttpClient) { }
saveFiles(total_form)
{
return this.http.post("http://localhost:8181/uploadFiles",total_form);
}
}
UploadController.java
@PostMapping("uploadFiles")
public String uploadMultiFiles(HttpServletRequest request)
{
System.out.println("hitting uploadFiles");
Enumeration e =request.getParameterNames();
while(e.hasMoreElements())
{
System.out.println(e.nextElement());
}
MultipartHttpServletRequest multiPartRequest = new DefaultMultipartHttpServletRequest(request);
try {
multiPartRequest = (MultipartHttpServletRequest) request;
multiPartRequest.getParameterMap();
//multipartRequest.
Iterator < String > it = multiPartRequest.getFileNames();
int i = 1;
while (it.hasNext()) {
MultipartFile multipart = multiPartRequest.getFile(it.next());
System.out.println("File name is "+multipart.getOriginalFilename());
}
}catch(Exception ex) {
}
return "uploaded ";
}
After trying with different scenarios to rendering the formdata object, I succeed in one scenario.
GitHub Link: Source
Updated files
multi-files-upload.component.html
multi-files-upload.component.ts
Multifiles.service.ts
MultiFileController.java
If you don't understand the code please fork it to your repository then clone and debug with console logs then you can clearly understand the code. Thanks