效果圖:
file-input.component.ts
import {
Component,
ElementRef,
EventEmitter,
HostListener,
Input,
Output,
} from '@angular/core';
@Component({
selector: 'app-file-input',
templateUrl: './file-input.html',
styleUrls: ['./file-input.scss']
})
export class FileInputComponent {
public isDrag: boolean = false;
public progress = 30;
public progressDisplay = false;
public filenameDisplay = false;
public fileName = '';
public filePath: any;
@Output() fileRead: EventEmitter<any> = new EventEmitter();
@Output() fileCancel: EventEmitter<any> = new EventEmitter();
@Output() fileUpload: EventEmitter<any> = new EventEmitter();
@Input() messages: string[] = [];
@Input() inputShowFile: string = '0';
constructor(public el: ElementRef) {}
@HostListener('drop', ['$event'])
onDrop(ev: any) {
ev.preventDefault();
this.progressDisplay = true;
let files = [];
[].forEach.call(ev.dataTransfer.files, function(file) {
files.push(file);
},false);
console.log(files);
const file: any = ev.dataTransfer.files[0];
this.messages.splice(0);
this.fileRead.emit(ev);
const temp = setInterval(() => {
this.clearPross(temp, file);
}, 100);
}
@HostListener('dragleave', ['$event'])
onDragLeave(ev: Event) {
ev.preventDefault();
this.isDrag = false;
}
@HostListener('dragover', ['$event'])
onDragOver(ev: Event) {
ev.preventDefault();
this.isDrag = true;
}
@HostListener('dragenter', ['$event'])
onDragEnter(ev: Event) {
ev.preventDefault();
this.isDrag = true;
}
public cancel(): void {
this.filenameDisplay = false;
this.progress = 30;
this.fileName = '';
this.messages.splice(0);
this.fileCancel.emit();
}
private clearPross(pro: any, file: any): void {
this.progress = this.progress + 30;
if (this.progress > 100) {
this.progress = 100;
clearInterval(pro);
setTimeout(() => {
this.progressDisplay = false;
this.fileName = file.name;
this.filenameDisplay = true;
this.isDrag = false;
this.progress = 0;
}, 100);
}
}
public openFile(): void {
this.el.nativeElement.querySelector('#file-input-read').click();
this.progress = 0;
this.filePath = undefined;
}
public fileChoose(event?: any): void {
if (event) {
event.preventDefault();
this.progressDisplay = true;
const file: any = this.getDocInfo(event);
this.messages.splice(0);
setTimeout(() => {
this.fileRead.emit(event);
}, 500);
const temp = setInterval(() => {
this.clearPross(temp, file);
}, 100);
}
this.filePath = undefined;
}
public upload(): void {
this.fileUpload.emit();
}
public getDocInfo(event: any): any {
const fileToUpload = event.dataTransfer ? event.dataTransfer.files[0] : event.target.files[0];
const fileName = fileToUpload.name;
const fileSize = fileToUpload.size;
const lastModifiedDate = fileToUpload.lastModifiedDate;
const date = new Date(lastModifiedDate);
const modifiedDate = date.getFullYear().toString() + '-' + this.dateTemp(date.getMonth()) + '-' + this.dateTemp(date.getDate()) + ' ' + this.dateTemp(date.getHours()) + ':' + this.dateTemp(date.getMinutes()) + ':' + this.dateTemp(date.getSeconds());
const file = { name: fileName, size: fileSize, modifiedDate: modifiedDate };
return file;
}
private dateTemp(num: number): any {
return (Array(2).join('0') + num).slice(-2).toString();
}
}
file-input.html
<ion-list class="file-input-list">
<ion-item lines="none" class="file-input" [ngClass]="{'file-input-drag':isDrag, 'file-input-drag-error':messages.length !== 0}">
<ion-chip (click)="openFile()">
<ion-icon name="search"></ion-icon>
<ion-label>文件選擇或者拖動文件到此</ion-label>
</ion-chip>
<input type="file" id='file-input-read' [(ngModel)]="filePath" (change)="fileChoose($event)" style="display: none;">
<ion-button [disabled]="fileName == ''" size="default" (click)="upload()">上傳</ion-button>
</ion-item>
<ion-progress-bar [value]="progress" max='100' *ngIf="messages.length === 0 && progressDisplay"></ion-progress-bar>
<ion-chip (click)="openFile()" [color]="messages.length !== 0?'warning':'primary'" *ngIf="filenameDisplay && inputShowFile == '0'">
{{fileName}}
<ion-icon name="close" (click)="cancel()"></ion-icon>
</ion-chip>
<ng-container *ngIf="messages.length !== 0">
<ng-container *ngFor="let message of messages; let i = index">
<ion-item lines="none" color="warning" class="file-input-error">{{message}}</ion-item>
</ng-container>
</ng-container>
</ion-list>
file-input.scss
.file-input {
border: 1px solid #bcc4ca;
padding: 7px 0px;
}
.file-input-drag {
border: 1px dashed #054666;
padding: 7px 0px;
}
.file-input-drag-error {
border: 1px solid red;
padding: 7px 0px;
}
.file-input-error {
--min-height: 24px;
}
.file-input-list {
display: inline-grid;
}