import { Component , Input , ChangeDetectionStrategy , ElementRef , Renderer2 , TemplateRef , HostBinding , OnChanges , SimpleChanges } from '@angular/core' ; import { NG_VALUE_ACCESSOR , ControlValueAccessor , NG_VALIDATORS , Validator , AbstractControl , ValidationErrors } from '@angular/forms' ; import { trapEvent , uniqueId } from '../util/util' ; import { InputBoolean , InputNumber } from '../util/convert' ; import { isFileTypeAccepted } from './file-upload.util' ; @ Component ( { selector : 'ngl-file-upload' , changeDetection : ChangeDetectionStrategy . OnPush , templateUrl : './file-upload.html' , providers : [ { provide : NG_VALUE_ACCESSOR , useExisting : NglFileUpload , multi : true } , { provide : NG_VALIDATORS , useExisting : NglFileUpload , multi : true } ] , } ) export class NglFileUpload implements ControlValueAccessor , Validator , OnChanges { /**
     * Label that appears above the upload area.
     */ @ Input ( ) label : string | TemplateRef < any > ; /**
     * File types that can be accepted. See [input accept Attribute](https://www.w3schools.com/tags/att_input_accept.asp).
     */ @ Input ( ) accept : string | string [ ] = null ; /**
     * Whether file selection is disabled.
     */ @ Input ( ) @ InputBoolean ( ) disabled = false ; /**
      * How many files can be selected simultaneously. `0` means unlimited.
      */ @ Input ( ) @ InputNumber ( ) maxFiles = 1 ; /**
     * File size limit in bytes. `0` means unlimited.
     */ @ Input ( ) @ InputNumber ( ) maxFilesize = 0 ; /**
     * Message to display when there is in an error state.
     */ @ HostBinding ( 'class.slds-has-error' ) @ Input ( ) error : string | TemplateRef < any > = null ; /**
     * Text for button to open file selector.
     */ @ Input ( ) uploadButtonLabel = 'Upload Files' ; /**
     * Text to display inside drop zone.
     */ @ Input ( ) dropZoneLabel = 'or Drop Files' ; uid = uniqueId ( 'file-upload' ) ; isDragOver = false ; files : File [ ] = [ ] ; constructor ( private element , private renderer ) { this . renderer . addClass ( this . element . nativeElement , 'slds-form-element' ) ; } onChange : Function | null = null ; onTouched = ( ) => { } ; validatorChange = ( ) => { } ; writeValue ( value ) { this . files = value ; } registerOnChange ( fn ) { this . onChange = fn ; } registerOnTouched ( fn ) { this . onTouched = fn ; } registerOnValidatorChange ( fn ) { this . validatorChange = fn ; } setDisabledState ( isDisabled ) { this . disabled = isDisabled ; } validate ( c ) { const files = c . value as File [ ] ; if ( ! files || files . length === 0 ) { return null ; } if ( this . maxFiles > 0 && files . length > this . maxFiles ) { return { nglFileUpload : { maxFiles : files . length } } ; } for ( let i = 0 , n = files . length ; i < n ; i ++ ) { const file = files [ i ] ; if ( this . accept && ! isFileTypeAccepted ( this . accept , file ) ) { return { nglFileUpload : { invalidType : file } } ; } if ( this . maxFilesize && file . size > this . maxFilesize ) { return { nglFileUpload : { maxFilesize : file } } ; } } return null ; } ngOnChanges ( changes ) { if ( changes [ 'maxFiles' ] || changes [ 'maxFilesize' ] || changes [ 'accept' ] ) { this . validatorChange ( ) ; } } onDropZone ( evt ) { trapEvent ( evt ) ; if ( this . disabled ) { return ; } this . isDragOver = evt . type === 'dragover' ; if ( evt . type === 'drop' && evt . dataTransfer ) { this . select ( evt . dataTransfer . files ) ; } } onInputChange ( files ) { this . select ( files ) ; } private select ( files ) { this . onChange ( Array . from ( files ) ) ; } }