【问题标题】:How to get files from angular 2 onDrop event?如何从 Angular 2 onDrop 事件中获取文件?
【发布时间】:2017-08-16 16:02:32
【问题描述】:

我试过这样,但onDrop 方法在我放到它时不返回图像文件...

onDragStart(event, data: any) {
  event.dataTransfer.setData('data', data);
}
onDrop(event, data: any) {
  let dataTransfer = event.dataTransfer.getData('data');
  event.preventDefault();
}
allowDrop(event) {
  event.preventDefault();
}
<div (drop)="onDrop($event, dropData)" (dragover)="allowDrop($event)"></div>
<div (dragstart)="onDragStart($event, dragData)"></div>

有什么解决办法吗?

【问题讨论】:

  • 为什么要阻止事件的默认行为?
  • 如果不阻止,拖放将不起作用...

标签: javascript angular drag-and-drop image-upload


【解决方案1】:

onDrop 事件仅在 onDragOver 有 preventDefault()stopPropagation() 方法在事件上运行时触发。

HTML

<div
    (drop)="onDrop($event)"
    (dragover)="onDragOver($event)"
>
    Drop target
</div>

DropComponent.ts

export class DropComponent {
    onDrop(event) {
        event.preventDefault();
    }
    onDragOver(event) {
        event.stopPropagation();
        event.preventDefault();
    }
}

更新

这是必需的,因为默认情况下,浏览器会在拖放到 HTML 元素时阻止任何事情发生。更多信息请访问 MDN - Defining a valid drop zone

【讨论】:

  • 如果你能解释为什么会这样就太好了。
【解决方案2】:

下面是 Angular 2/4/6 中拖放的完整代码:

drag.component.ts:

import { Component } from '@angular/core';

@Component({
  selector: 'drag-root',
  templateUrl: './drag.component.html',
  styleUrls: ['./drag.component.css']
})
export class AppComponent {

  allowDrop(ev) {
    ev.preventDefault();
  }

  drag(ev) {
    ev.dataTransfer.setData("text", ev.target.id);
  }

  drop(ev) {
    ev.preventDefault();
    var data = ev.dataTransfer.getData("text");
    ev.target.appendChild(document.getElementById(data));
  }
}

拖动.component.html:

<h2>Drag and Drop</h2>
<div  id="div1" 
      (drop)="drop($event)" 
      (dragover)="allowDrop($event)">

      <img 
      src="https://images.pexels.com/photos/658687/pexels-photo-658687.jpeg?auto=compress&cs=tinysrgb&h=350" 
      draggable="true" 
      (dragstart)="drag($event)" 
      id="drag1"
      width="88" 
      height="31">
</div>

<div id="div2" 
  (drop)="drop($event)" 
  (dragover)="allowDrop($event)">
</div>

drag.component.css:

#div1, #div2 {
    float: left;
    width: 100px;
    height: 35px;
    margin: 10px;
    padding: 10px;
    border: 1px solid black;
}

快照:

【讨论】:

  • 它对我有用,但为了从 div 获取数据,我使用了下面的代码,它给出了文件 Object, var data = event.dataTransfer.files[0];
【解决方案3】:

您可以将 onDrop 功能包装到可重用指令中。像这样:

https://gist.github.com/darrenmothersele/7afda13d858a156ce571510dd78b7624

将此指令应用于元素:

<div (appDropZone)="onDrop($event)"></div>

该事件由已删除文件的 JavaScript 数组触发。因此,您在组件中的 onDrop 实现如下所示:

onDrop(files: FileList) {
  console.log({ files });
}

【讨论】:

    【解决方案4】:

    正如其他人所说,您需要在 (dragover) 事件上调用 event.preventDefault()event.stopPropagation() 以使您的容器成为有效的放置区。

    我编写了一个高度可定制的 Angular 组件,它实现了正确的 Drag'n'Drop 行为,因此我不需要一遍又一遍地复制它,它会返回一个已删除文件的列表作为输出事件。
    这可以找到here

    导入模块后,您可以访问组件:

    <ngx-dropzone [multiple]="false" [maxFileSize]="2000"></ngx-dropzone>
    

    您可以设置一些选项,它带有一个不错的默认样式(可以在 GitHub 存储库中找到屏幕截图)。如果您愿意,您甚至可以使用您自己的 div 容器和您的自定义样式和悬停效果,并将其放入 dropzone。可以在 API 描述中找到这方面的详细信息。

    <ngx-dropzone [customContent]="customDropzone" (filesAdded)="onFilesDropped($event)">
    <ng-template #customDropzone>
        <div class="custom-dropzone">
            This is my custom content
        </div>
    </ng-template>
    

    【讨论】:

    • 我为此花了一整天的时间,但您的组件在 3 分钟内完成。我有一个问题,我们可以在同一个保管箱中显示上传的图像吗?
    • @KishanOza 目前尚未实现,但我在 GitHub 上也收到了很多请求。我将尝试在接下来的几周内添加图像预览。我建议您“观看”存储库,以便了解更新。
    • 是的,我设法通过在数组中添加图像并分别显示它们来做到这一点。但如果我们可以在 self @PeterFreeman 的下拉框中显示相同的图像,那就太好了
    • 现在可以使用最新版本。 :)
    • 是的,这很酷..但它一次只显示一个图像..如果我删除新图像,​​它将覆盖前一个图像:(任何解决方案?并且没有删除该图像的选项:( 我正在创建类似 playstore 和 appstore 上传的 UI,用户可以在其中添加屏幕截图
    【解决方案5】:

    您可以尝试使用Hostlistener 装饰器进行拖动事件,您可以看到它已实现,例如here in ng2-file-upload

    【讨论】:

    • Hostlistener 将如何提供帮助?
    • 我尝试添加@HostListener('drop', ['$event']),但它仍然返回空事件...
    【解决方案6】:

    一个非常简单的指令,允许您将文件放置在任何位置。

    IE:

    @Directive({
      selector: '[dropFileZone]'
    })
    export class DropFileZoneDirective {
    
      @Output() onDropFile = new EventEmitter<File>();
      constructor() { }
    
      @HostListener('dragover', ['$event'])
      allowDrop(event) {
        event.stopPropagation();
        event.preventDefault();
        event.dataTransfer.dropEffect = 'copy';
      }
    
      @HostListener('drop', ['$event'])
      async onDrop(event) {
        event.stopPropagation();
        event.preventDefault();
        let fileList = event.dataTransfer.files; // Array of all files
        const fileExists: boolean = fileList.length > 0;
        if (!fileExists) {
          return;
        }
        this.onDropFile.emit(fileList[0]);
      }
    }
    

    在 .html 文件上使用它的方式:

    <div dropFileZone (onDropFile)="handleDroppedFile($event)"> </div>
    

    【讨论】:

      猜你喜欢
      • 2018-05-30
      • 2017-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多