@nghacks/uploader
Version:
Image and file uploader for angular
259 lines (250 loc) • 13.8 kB
JavaScript
import { Injectable, EventEmitter, Component, Output, Input, HostListener, NgModule } from '@angular/core';
import { __awaiter } from 'tslib';
import { FormControl } from '@angular/forms';
import { CommonModule } from '@angular/common';
class UploaderService {
constructor() { }
getBase64(file) {
const reader = new FileReader();
reader.readAsDataURL(file);
return new Promise(resolve => {
reader.onload = (event) => {
const res = event.target.result;
const base64Image = res.split(',');
return resolve(base64Image);
};
});
}
}
UploaderService.decorators = [
{ type: Injectable }
];
UploaderService.ctorParameters = () => [];
class BaseUploaderComponent {
constructor(_uploaderService) {
this._uploaderService = _uploaderService;
this.fileInputChange = new EventEmitter();
this.formCtrl = new FormControl();
/**
* @description maximum file size in kb (kilobyte)
* @default 5000 (5mb)
*/
this.maxSize = 5000;
/**
* @description min-height of the picker
* @default 48 (in pixel)
*/
this.minHeight = 48;
}
// Dragover listener
onDragOver(evt) {
evt.preventDefault();
evt.stopPropagation();
this.dragover = true;
}
// Dragleave listener
onDragLeave(evt) {
evt.preventDefault();
evt.stopPropagation();
this.dragover = false;
}
// Drop listener
ondrop(evt) {
evt.preventDefault();
evt.stopPropagation();
if (evt.dataTransfer.files && evt.dataTransfer.files[0]) {
this.addFile(evt.dataTransfer.files[0]);
}
this.dragover = false;
}
// Choose listener
inputChange(event) {
return __awaiter(this, void 0, void 0, function* () {
if (event.target.files && event.target.files[0]) {
this.addFile(event.target.files[0]);
}
});
}
addFile(file) {
return __awaiter(this, void 0, void 0, function* () {
if (!file) {
return;
}
if (this.formCtrl.disabled) {
return;
}
const errors = this.validate(file);
const fileName = file.name;
const base64Image = yield this._uploaderService.getBase64(file);
this.fileInputChangeStore = {
hasFile: true,
fileName,
errors,
base64Image
};
this.fileInputChange.emit(this.fileInputChangeStore);
this.formCtrl.setValue(base64Image);
});
}
validate(file) {
let isSizeValid = true;
if ((file.size / 1000) > this.maxSize) {
isSizeValid = false;
}
let isTypeValid = false;
for (const type of this.accept) {
if (type.split('.')[1] === file.type.split('/')[1]) {
isTypeValid = true;
}
}
return this.getError(isSizeValid, isTypeValid);
}
getError(size, type) {
let errors;
if (size && type) {
errors = {
maxSizeExceeded: null,
wrongFileType: null
};
}
else if (!size && type) {
errors = {
maxSizeExceeded: true,
wrongFileType: null
};
}
else if (size && !type) {
errors = {
maxSizeExceeded: null,
wrongFileType: true
};
}
else {
errors = {
wrongFileType: true,
maxSizeExceeded: true
};
}
return errors;
}
getImageHeightWidth(base64Image) {
return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
const image = new Image();
image.src = base64Image;
image.onload = () => {
return resolve({
height: image.height,
width: image.width
});
};
}));
}
removeFile() {
this.fileInputChangeStore = {
hasFile: false,
fileName: null,
errors: null,
base64Image: null
};
this.fileInputChange.emit(this.fileInputChangeStore);
this.formCtrl.setValue('');
}
}
BaseUploaderComponent.decorators = [
{ type: Component, args: [{ template: '' },] }
];
BaseUploaderComponent.ctorParameters = () => [
{ type: UploaderService }
];
BaseUploaderComponent.propDecorators = {
fileInputChange: [{ type: Output }],
pickerLabel: [{ type: Input }],
hint: [{ type: Input }],
accept: [{ type: Input }],
maxSize: [{ type: Input }],
disabled: [{ type: Input }],
minHeight: [{ type: Input }],
onDragOver: [{ type: HostListener, args: ['dragover', ['$event'],] }],
onDragLeave: [{ type: HostListener, args: ['dragleave', ['$event'],] }],
ondrop: [{ type: HostListener, args: ['drop', ['$event'],] }]
};
class FileUploaderComponent extends BaseUploaderComponent {
constructor() {
super(...arguments);
/**
* @default 'Drag file, or Choose''
*/
this.pickerLabel = 'Drag file, or Choose';
/**
* @default ['.pdf', '.csv', '.doc', '.docx','.docx', '.xlsx', '.cer']
*/
this.accept = ['.pdf', '.csv', '.doc', '.docx', '.docx', '.xlsx', '.cer'];
}
}
FileUploaderComponent.decorators = [
{ type: Component, args: [{
selector: 'file-uploader',
template: "<div class=\"uploader file-preview\"\n [ngStyle]=\"{\n 'min-height': minHeight+'px'\n }\"\n [ngClass]=\"{\n 'dragover': dragover,\n 'disabled': disabled\n }\">\n\n <div\n (click)=\"uploader.click()\"\n class=\"file\"\n *ngIf=\"formCtrl.value; else nofile\">\n <span class=\"file-name\">{{fileInputChangeStore.fileName}}</span>\n </div>\n\n <ng-template #nofile>\n <button class=\"picker\" type=\"button\" (click)=\"uploader.click()\">\n {{pickerLabel}}\n </button>\n </ng-template>\n\n <div class=\"cross\" *ngIf=\"formCtrl.value\">\n <button type=\"button\" (click)=\"removeFile()\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M16.3394 9.32245C16.7434 8.94589 16.7657 8.31312 16.3891 7.90911C16.0126 7.50509 15.3798 7.48283 14.9758 7.85938L12.0497 10.5866L9.32245 7.66048C8.94589 7.25647 8.31312 7.23421 7.90911 7.61076C7.50509 7.98731 7.48283 8.62008 7.85938 9.0241L10.5866 11.9502L7.66048 14.6775C7.25647 15.054 7.23421 15.6868 7.61076 16.0908C7.98731 16.4948 8.62008 16.5171 9.0241 16.1405L11.9502 13.4133L14.6775 16.3394C15.054 16.7434 15.6868 16.7657 16.0908 16.3891C16.4948 16.0126 16.5171 15.3798 16.1405 14.9758L13.4133 12.0497L16.3394 9.32245Z\"\n fill=\"currentColor\" />\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M1 12C1 5.92487 5.92487 1 12 1C18.0751 1 23 5.92487 23 12C23 18.0751 18.0751 23 12 23C5.92487 23 1 18.0751 1 12ZM12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12C21 16.9706 16.9706 21 12 21Z\"\n fill=\"currentColor\" />\n </svg>\n </button>\n </div>\n\n <div class=\"hint\" *ngIf=\"hint\">\n <span>{{hint}}</span>\n </div>\n\n</div>\n\n\n<!-- Image Input -->\n<input #uploader type='file' style=\"display: none;\" [accept]=\"accept\" [disabled]=\"disabled\"\n (change)=\"inputChange($event);uploader.value=''\">\n",
styles: ["button{background:none;border:none;cursor:pointer;outline:none;padding:0}.uploader{border:1px solid #e0e0e0;border-radius:5px;box-sizing:border-box;margin-bottom:25px;min-height:48px;position:relative;transition:all .2s;width:100%}.uploader.dragover,.uploader:hover{background-color:#e4e4e4;border:1px dashed #1b7937}.uploader .cross{position:absolute;right:10px;top:10px}.uploader .picker{align-items:center;bottom:0;display:flex;height:100%;justify-content:center;left:0;padding:10px;position:absolute;right:0;top:0;width:100%}.uploader .hint{bottom:-25px;font-size:12px;left:0;position:absolute}.uploader.disabled{background-color:initial;border:1px dashed #b8b6b6;color:#b8b6b6}.uploader.disabled .picker{cursor:not-allowed!important}.uploader.disabled .cross,.uploader.disabled .hint{display:none}.uploader.file-preview{cursor:pointer;position:relative}.uploader.file-preview .file{align-items:center;box-sizing:border-box;display:flex;height:100%;justify-content:center;overflow:hidden;padding:10px;position:absolute;width:100%}.uploader.file-preview .file .file-name{font-weight:700;overflow:hidden;text-align:center;text-overflow:ellipsis;white-space:nowrap;width:100%}"]
},] }
];
FileUploaderComponent.propDecorators = {
pickerLabel: [{ type: Input }],
accept: [{ type: Input }]
};
class ImgUploaderComponent extends BaseUploaderComponent {
constructor() {
super(...arguments);
/**
* @default 'Drag image, or Choose'
*/
this.pickerLabel = 'Drag image, or Choose';
/**
* @default ['.jpg', '.png', '.jpeg']
*/
this.accept = ['.jpg', '.png', '.jpeg'];
/**
* @description max-height of the image previewer
* @memberof ImgUploaderComponent
*/
this.maxHeight = 250;
}
}
ImgUploaderComponent.decorators = [
{ type: Component, args: [{
selector: 'img-uploader',
template: "<div class=\"uploader image-preview\"\n [ngStyle]=\"{\n 'min-height': minHeight+'px'\n }\"\n [ngClass]=\"{\n 'dragover': dragover,\n 'disabled': disabled\n }\">\n\n <div\n (click)=\"uploader.click()\"\n class=\"image\"\n [ngStyle]=\"{\n 'max-height': maxHeight+'px'\n }\"\n *ngIf=\"formCtrl.value; else nofile\">\n\n <img\n [ngStyle]=\"{\n 'max-height': (maxHeight-(10*2))+'px'\n }\"\n [src]=\"formCtrl.value\" />\n\n </div>\n\n <ng-template #nofile>\n <button class=\"picker\" type=\"button\" (click)=\"uploader.click()\">\n {{pickerLabel}}\n </button>\n </ng-template>\n\n <div class=\"cross\" *ngIf=\"formCtrl.value\">\n <button type=\"button\" (click)=\"removeFile()\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M16.3394 9.32245C16.7434 8.94589 16.7657 8.31312 16.3891 7.90911C16.0126 7.50509 15.3798 7.48283 14.9758 7.85938L12.0497 10.5866L9.32245 7.66048C8.94589 7.25647 8.31312 7.23421 7.90911 7.61076C7.50509 7.98731 7.48283 8.62008 7.85938 9.0241L10.5866 11.9502L7.66048 14.6775C7.25647 15.054 7.23421 15.6868 7.61076 16.0908C7.98731 16.4948 8.62008 16.5171 9.0241 16.1405L11.9502 13.4133L14.6775 16.3394C15.054 16.7434 15.6868 16.7657 16.0908 16.3891C16.4948 16.0126 16.5171 15.3798 16.1405 14.9758L13.4133 12.0497L16.3394 9.32245Z\"\n fill=\"currentColor\" />\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M1 12C1 5.92487 5.92487 1 12 1C18.0751 1 23 5.92487 23 12C23 18.0751 18.0751 23 12 23C5.92487 23 1 18.0751 1 12ZM12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12C21 16.9706 16.9706 21 12 21Z\"\n fill=\"currentColor\" />\n </svg>\n </button>\n </div>\n\n <div class=\"hint\" *ngIf=\"hint\">\n <span>{{hint}}</span>\n </div>\n\n</div>\n\n\n<!-- Image Input -->\n<input #uploader type='file' style=\"display: none;\" [accept]=\"accept\" [disabled]=\"disabled\"\n (change)=\"inputChange($event);uploader.value=''\">\n",
styles: ["button{background:none;border:none;cursor:pointer;outline:none;padding:0}.uploader{border:1px solid #e0e0e0;border-radius:5px;box-sizing:border-box;margin-bottom:25px;min-height:48px;position:relative;transition:all .2s;width:100%}.uploader.dragover,.uploader:hover{background-color:#e4e4e4;border:1px dashed #1b7937}.uploader .cross{position:absolute;right:10px;top:10px}.uploader .picker{align-items:center;bottom:0;display:flex;height:100%;justify-content:center;left:0;padding:10px;position:absolute;right:0;top:0;width:100%}.uploader .hint{bottom:-25px;font-size:12px;left:0;position:absolute}.uploader.disabled{background-color:initial;border:1px dashed #b8b6b6;color:#b8b6b6}.uploader.disabled .picker{cursor:not-allowed!important}.uploader.disabled .cross,.uploader.disabled .hint{display:none}.uploader.image-preview{cursor:pointer;position:relative}.uploader.image-preview .image{align-items:center;box-sizing:border-box;display:flex;justify-content:center;padding:10px}.uploader.image-preview .image img{height:100%!important;max-width:100%;width:auto}"]
},] }
];
ImgUploaderComponent.propDecorators = {
pickerLabel: [{ type: Input }],
accept: [{ type: Input }],
maxHeight: [{ type: Input }]
};
class UploaderModule {
}
UploaderModule.decorators = [
{ type: NgModule, args: [{
declarations: [
ImgUploaderComponent,
FileUploaderComponent
],
imports: [
CommonModule
],
providers: [UploaderService],
exports: [
ImgUploaderComponent,
FileUploaderComponent
],
},] }
];
/*
* Public API Surface of uploader
*/
/**
* Generated bundle index. Do not edit.
*/
export { FileUploaderComponent, ImgUploaderComponent, UploaderModule, BaseUploaderComponent as ɵa, UploaderService as ɵb };
//# sourceMappingURL=nghacks-uploader.js.map