I am working on an app in Angular 14 with includes a form. The form has a file uploader.
In form.component.ts
I have:
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { FormService } from '../services/form.service';
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.css'],
})
export class FormComponent {
@ViewChild('fileDropRef', { static: false })
public fileDropEl!: ElementRef;
public files: any[] = [];
public form: FormGroup = new FormGroup({
first_name: new FormControl('', Validators.required),
last_name: new FormControl('', Validators.required),
email: new FormControl('', [Validators.required, Validators.email]),
imageName: new FormControl(''),
});
constructor(private formService: FormService) {}
ngOnInit(): void {}
// File uploader Begin
public onFileDropped($event: any) {
this.prepareFilesList($event);
}
public fileBrowseHandler(files: any) {
this.prepareFilesList(files);
}
public deleteFile(index: number) {
if (this.files[index].progress < 100) {
console.log('Upload in progress.');
return;
}
this.files.splice(index, 1);
}
public uploadFilesSimulator(index: number) {
setTimeout(() => {
if (index === this.files.length) {
return;
} else {
const progressInterval = setInterval(() => {
if (this.files[index].progress === 100) {
clearInterval(progressInterval);
this.uploadFilesSimulator(index 1);
} else {
this.files[index].progress = 5;
}
}, 200);
}
}, 1000);
}
public prepareFilesList(files: Array<any>) {
for (const item of files) {
item.progress = 0;
this.files.push(item);
}
this.fileDropEl.nativeElement.value = '';
this.uploadFilesSimulator(0);
}
public formatBytes(bytes: number, decimals: number = 2) {
if (bytes === 0) {
return '0 Bytes';
}
const k = 1024;
const dm = decimals <= 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) ' ' sizes[i];
}
// File uploader End
public sendFormData() {
this.formService
.sendFormData(this.formService.value)
.subscribe((response) => {});
}
}
In the template, the file uploader looks like this:
<div >
<div appDnd (fileDropped)="onFileDropped($event)">
<input formControlName="imageName" type="file" #fileDropRef id="fileDropRef" multiple />
<div >
<h3 >Drop your file to upload</h3>
<h3 >or</h3>
<label for="fileDropRef">Browse for file</label>
</div>
</div>
<div >
<div *ngFor="let file of files; let i = index">
<img
src="../../assets/images/dnd/ic-file.svg"
alt=""
/>
<div >
<p >{{ file?.name }}</p>
<p >{{ formatBytes(file?.size) }}</p>
<app-progress [progress]="file?.progress"></app-progress>
</div>
<img
src="../../assets/images/dnd/ic-delete-file.svg"
width="20px"
alt="file"
(click)="deleteFile(i)"
/>
</div>
</div>
</div>
There is a Stackblitz HERE.
The problem
Although the file uploader works as expected when the user drags a file over it, displaying the upload progress, it fails when browsing for the file.
Questions
- What am I doing wrong?
- How can I fix the problem?
CodePudding user response:
salutare:) you need to trigger "onFileDropped" also in file selection:
<input #inputType type="file" #fileDropRef id="fileDropRef" multiple (change)="onFileChange($event)"/>
onFileChange(event: any) {
const files = event.target.files;
this.onFileDropped(files);
}