0

I'm trying to create a files-drag & drop zone in Angular. I created dropzone.directive and added it to the declarations in app.module.ts.

My code compiles and I can launch everything. But when I try to drag files, the html doesn't respond to the files I drag over the zone. I have the feeling that I am missing something obvious which prevents dropzone.directive from getting activated.

How come directive.ts doesn't seem to get triggered?

My problem can easily be reproduced: You can just copy and paste the code below, there are no special imports required.

My dropzone.directive.ts reads as follows:

import { Directive, EventEmitter, HostBinding, HostListener, Output } from '@angular/core';

@Directive({
  selector: '[Dropzone]'
})
export class DropzoneDirective {
  @Output() onFileDropped = new EventEmitter<any>();

  @HostBinding('style.opacity') private opacity = '1';
  @HostBinding('style.border') private border = 'none';

  @HostListener('dragover', ['$event']) public onDragOver(evt: any): any {
    evt.preventDefault();
    evt.stopPropagation();
    this.opacity = '0.8';
    this.border = 'dotted 2px #FF4D2A';
  }

  @HostListener('dragleave', ['$event']) public onDragLeave(evt: any): any {
    evt.preventDefault();
    evt.stopPropagation();
    this.opacity = '1';
    this.border = 'none';
  }

  @HostListener('drop', ['$event']) public ondrop(evt: any): any {
    evt.preventDefault();
    evt.stopPropagation();
    this.opacity = '1';
    this.border = 'none';
    const files = evt.dataTransfer.files;
    if (files.length > 0) {
      this.onFileDropped.emit(files);
    }
  }
  

}

Then I declare my directive in the app.module:

import { DropzoneDirective } from './dropzone.directive';

@NgModule({
  declarations: [
    .....,
    DropzoneDirective
  ],
  imports: [
     ...,
    ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

My component.ts:


export class WebshopOverzichtComponent implements OnInit {
  allFiles: File[] = [];

  constructor() { }

  droppedFiles(allFiles: File[]| any): void {
    const filesAmount = allFiles.length;
    for (let i = 0; i < filesAmount; i++) {
      const file = allFiles[i];
      this.allFiles.push(file);
    }
  }
}

And finally, my component.html:

<div class="container text-center mt-5">
    <h3 class="mb-5"> Drop zone Dragondrop </h3>
    <!-- Applying Directive -->
    <div class="dropzone" DropZone (onFileDropped)="droppedFiles($event)">
      <div class="text-center">
        Drop files here.<BR>
      </div>
    </div>
    <div class="file-table">
      <h3 class="m-3">List of Files</h3>
      <table class="table">
        <thead>
          <tr>
            <th scope="col">#</th>
            <th scope="col">File Name</th>
            <th scope="col">Size</th>
            <th scope="col">Type</th>
          </tr>
        </thead>
        <tbody>
          <tr *ngFor="let file of allFiles; let i = index">
            <th scope="row">{{i+1}}</th>
            <td>{{file.name}}</td>
            <td>{{file.size}} Bytes</td>
            <td>{{file.type}}</td>
          </tr>
          <tr class="text-center" *ngIf="allFiles.length === 0">
            <td colspan="4"><strong>No files are uploaded</strong></td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
kellermat
  • 2,859
  • 2
  • 4
  • 21

1 Answers1

0

You don't even need to use directive. Just use the input tag, set it on type="file" and use annotation multipe. Set the opacity in css en enlarge the input. Use the function in ts that I gave. It will work as drag & drop zone. Make a seperate button to perform the upload.

            <div class="file-container">
                <input class="file" type="file" multiple 
(change)="onFileChange($event)" >
              </div>

  <button class="btn btn-primary" [disabled]="allFiles.length==0" (click)="uploadFiles(product.webshopnaam)">Upload</button>

css

 .file-container{
    width: 300px;
    border: 4px dotted black;
 }

 .file{
    opacity: 0;
    padding: 1rem;
    width: auto;
    height: 1rem;
 }

ts

 allFiles: File[] = [];

onFileChange(event:any) {
   
  for (var i = 0; i < event.target.files.length; i++) { 
      this.allFiles.push(event.target.files[i]);
  }
  this.allFiles.forEach(value => console.log(value.name));

}

  async uploadFiles(naam:string):Promise<void>{
    this.productService.uploadImages(this.allFiles, naam);
  }
onFileChange(event:any) {
   
  for (var i = 0; i < event.target.files.length; i++) { 
      this.allFiles.push(event.target.files[i]);
  }
  this.allFiles.forEach(value => console.log(value.name));

}

  async uploadFiles(naam:string):Promise<void>{
    this.productService.uploadImages(this.allFiles, naam);
  }

Yannick Mussche
  • 316
  • 2
  • 12