src/app/components/file-upload/file-upload.component.ts
ControlValueAccessor
Validator
providers |
{
provide: NG_VALUE_ACCESSOR, multi: true, useExisting: FileUploadComponent,
}
{
provide: NG_VALIDATORS, multi: true, useExisting: FileUploadComponent,
}
|
selector | app-file-upload |
styleUrls | ./file-upload.component.scss |
templateUrl | ./file-upload.component.html |
Properties |
Methods |
Outputs |
fileFormDataEvent | |
Type : EventEmitter
|
|
onClick | ||||||
onClick(fileUpload: HTMLInputElement)
|
||||||
Parameters :
Returns :
void
|
onFileSelected | ||||||
onFileSelected(event: Event)
|
||||||
Parameters :
Returns :
void
|
registerOnChange | ||||||
registerOnChange(onChange: (value: string) => void)
|
||||||
Parameters :
Returns :
void
|
registerOnTouched | ||||||
registerOnTouched(onTouched: () => void)
|
||||||
Parameters :
Returns :
void
|
registerOnValidatorChange | ||||||
registerOnValidatorChange(onValidatorChange: () => void)
|
||||||
Parameters :
Returns :
void
|
validate | ||||||
validate(_control: AbstractControl)
|
||||||
Parameters :
Returns :
ValidationErrors | null
|
writeValue | ||||||
writeValue(value: string)
|
||||||
Parameters :
Returns :
void
|
fileName |
Type : string
|
Default value : ''
|
fileUploadError |
Default value : false
|
onChange |
Default value : () => {...}
|
onTouched |
Default value : () => {...}
|
onValidatorChange |
Default value : () => {...}
|
import { Component, EventEmitter, Output } from '@angular/core';
import {
AbstractControl,
ControlValueAccessor,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
ValidationErrors,
Validator,
} from '@angular/forms';
@Component({
selector: 'app-file-upload',
templateUrl: './file-upload.component.html',
styleUrls: ['./file-upload.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: FileUploadComponent,
},
{
provide: NG_VALIDATORS,
multi: true,
useExisting: FileUploadComponent,
},
],
})
export class FileUploadComponent implements ControlValueAccessor, Validator {
fileName = '';
@Output() fileFormDataEvent = new EventEmitter<FormData>();
onFileSelected(event: Event) {
const file = (event.target as HTMLInputElement | null)?.files?.[0];
if (file) {
this.fileName = file.name;
const formData = new FormData();
formData.append('csvFile', file);
this.fileFormDataEvent.emit(formData);
this.onChange(this.fileName);
}
}
fileUploadError = false;
onChange = (_fileName: string) => {};
onTouched = () => {};
onValidatorChange = () => {};
onClick(fileUpload: HTMLInputElement) {
this.onTouched();
fileUpload.click();
}
writeValue(value: string) {
this.fileName = value;
}
registerOnChange(onChange: (value: string) => void) {
this.onChange = onChange;
}
registerOnTouched(onTouched: () => void) {
this.onTouched = onTouched;
}
registerOnValidatorChange(onValidatorChange: () => void) {
this.onValidatorChange = onValidatorChange;
}
validate(_control: AbstractControl): ValidationErrors | null {
return null;
}
}
<input type="file" class="file-input" required accept=".csv" (change)="onFileSelected($event)" #fileUpload />
<button class="file-upload" color="primary" class="upload-btn" (click)="onClick(fileUpload)">
<mat-icon>upload_file</mat-icon>
Upload file (CSV or XLSX)
</button>
<div class="file-name">
{{ fileName || 'No file loaded' }}
</div>
./file-upload.component.scss
:host {
display: block;
width: 25rem;
height: 6.25rem;
.file-input {
display: none;
}
.file-upload {
color: #757575;
}
button {
margin-top: 2rem;
display: flex;
width: 14.688rem;
height: 3.125rem;
align-items: center;
background: white;
border-radius: 0.3rem;
border-color: #9d9e9a;
border-style: solid;
}
mat-icon {
color: #9d9e9a;
}
.file-name {
padding-top: 0.7rem;
}
}