All files / lib/dynamic-form-input/dynamic-form-file dynamic-form-file.directive.ts

100% Statements 43/43
93.33% Branches 14/15
100% Functions 16/16
100% Lines 41/41

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100                  1x 19x 19x 19x           19x     19x   19x   12x 4x 4x     9x 9x 9x 9x       14x 5x   14x 5x 5x 2x 3x 1x           1x         5x 3x 3x       9x 9x       19x       18x       56x       6x       13x 9x 9x 9x     4x 4x 4x     13x 4x        
import { Directive, ElementRef, HostListener, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { DynamicFormFileUpload } from './dynamic-form-file';
 
@Directive({
  selector: '[dynamicFormFile]',
  exportAs: 'dynamicFormFile',
  providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: DynamicFormFileDirective, multi: true }],
})
export class DynamicFormFileDirective implements ControlValueAccessor, OnInit, OnChanges {
  private _files: DynamicFormFileUpload[] = null;
  private _fileNames: string[] = null;
  private _fileNamesAsText: string = null;
 
  protected _onChange: any;
  protected _onTouched: any;
 
  @Input()
  acceptFiles = '';
 
  @Input()
  multipleFiles = false;
 
  constructor(private elementRef: ElementRef<HTMLInputElement>) {}
 
  get files(): DynamicFormFileUpload[] { return this._files; }
  get fileNames(): string[] { return this._fileNames; }
  get fileNamesAsText(): string { return this._fileNamesAsText; }
 
  ngOnInit(): void {
    this.nativeElement.type = 'file';
    this.nativeElement.hidden = true;
    this.nativeElement.accept = this.acceptFiles;
    this.nativeElement.multiple = this.multipleFiles;
  }
 
  ngOnChanges({ acceptFiles, multipleFiles }: SimpleChanges): void {
    if (!acceptFiles?.firstChange) {
      this.nativeElement.accept = this.acceptFiles;
    }
    if (!multipleFiles?.firstChange) {
      this.nativeElement.multiple = this.multipleFiles;
      if (this.multipleFiles) {
        this.changeFiles();
      } else if (this._files?.length > 0) {
        this.setFiles([ this._files[0] ]);
      }
    }
  }
 
  openFileExplorer(): void {
    this.nativeElement.click();
  }
 
  @HostListener('change', ['$event.target.files'])
  uploadFiles(fileList: FileList): void {
    const files = Array.from(fileList).map(file => new DynamicFormFileUpload(file));
    this.setFiles(files);
    this._onTouched?.();
  }
 
  writeValue(_value: any): void {
    this.setFiles(null, false);
    this.nativeElement.value = '';
  }
 
  registerOnChange(onChange: any): void {
    this._onChange = onChange;
  }
 
  registerOnTouched(onTouched: any): void {
    this._onTouched = onTouched;
  }
 
  private get nativeElement(): HTMLInputElement {
    return this.elementRef.nativeElement;
  }
 
  private changeFiles(): void {
    this._onChange?.(this.multipleFiles ? this._files : this._files?.[0] || null);
  }
 
  private setFiles(files: DynamicFormFileUpload[], changeFiles: boolean = true): void {
    if (!files?.length) {
      this._files = null;
      this._fileNames = null;
      this._fileNamesAsText = null;
 
    } else {
      this._files = files;
      this._fileNames = this.multipleFiles ? this._files.map(f => f.name) : [ this._files[0].name ];
      this._fileNamesAsText = this._fileNames.join(', ');
    }
 
    if (changeFiles) {
      this.changeFiles();
    }
  }
}