使用 Angular 4 拖放 HTML 5

Posted

技术标签:

【中文标题】使用 Angular 4 拖放 HTML 5【英文标题】:HTML 5 Drag & Drop with Angular 4 【发布时间】:2018-06-07 02:21:57 【问题描述】:

我正在尝试让原生 html 5 拖放在我的 Angular 应用程序中工作。我得到了拖动,触发了拖动和 dragOver 事件,但不幸的是 drop 没有触发任何东西。这里我有下面的 HTML 和拖动事件代码。

<ul *ngFor="let channel of channelList" >
      <li class="list-group-item" *ngIf="channel.channel.substr(0, 1) === head" 
      style="float:left; margin:0.5px" draggable="true" (dragstart)="drag(channel)">
        <ng-container *ngIf="channel.compChannel.compChannelLogo.length !== 0; else noCompChannel">
          <img class="img-rounded" src=" channel.logo "   >
          <img class="img-rounded" src=" channel.compChannel.compChannelLogo "   >
        </ng-container>
        <ng-template #noCompChannel>
          <img class="img-rounded" src=" channel.logo "  
            >
        </ng-template>
      </li>
    </ul>
<ul class="list-group" *ngFor="let channels of currentPickSelection" dropzone="copy">
  <li class="list-group-item" style="float:Left; margin-left:0.5px" (dragover)="dragOver(channels[0])" (dragend)="drop(event)">
    <ng-container *ngIf="channels[0].compChannel.compChannelLogo.length !== 0; else noCompChannel">
      <img class="img-rounded" src=" channels[0].logo "   >
      <img class="img-rounded" src=" channels[0].compChannel.compChannelLogo " 
         >
    </ng-container>
    <ng-template #noCompChannel>
      <img class="img-rounded" src=" channels[0].logo "   >
    </ng-template>
    <br>
    <strong>
      <font size="2"> channels[0].pickCode </font>
    </strong>
  </li>
</ul>



drag(channel) 
    console.log(channel);
  
  dragOver(channel) 
    this.draggedChannel = channel;
    // console.log(this.draggedChannel);
  

  drop(e) 
    console.log(e);
  

【问题讨论】:

你使用过LibraryPackage进行拖放吗? 不,我只是使用原生 HTML 5 你试过ondrop="drop(event)"吗? drop 根本不触发。 【参考方案1】:

我在 Angular 2/4/5/6 中没有任何其他模块,您也可以使用以下代码来制作它:

拖动.component.html:

<h2>Drag and Drop demo</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"
       
      >
</div>

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

drag.component.ts:

import  Component  from '@angular/core';

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

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

  allowDrop(ev) 
    ev.preventDefault();
  

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

drag.component.css:

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

Stackblitz example

【讨论】:

【参考方案2】:
<div (dragover)="onDragOver($event)" 
     (dragleave)="onDragLeave($event)" (drop)="onDrop($event)">
</div>

在您的组件中:

onDrop(event: any) 
    event.preventDefault();
    event.stopPropagation();
    // your code goes here after droping files or any


onDragOver(evt) 
    evt.preventDefault();
    evt.stopPropagation();


onDragLeave(evt) 
    evt.preventDefault();
    evt.stopPropagation();

【讨论】:

dragLeave 触发,但我不知道如何使用它。 drop 事件根本不会触发。 为了处理drop事件,你必须在dragover handler中添加event.preventDefault()【参考方案3】:

要在 Angular 4 应用程序中使用拖放,您可以使用 npm 模块“ngx-uploader”。

您将在以下链接中找到集成步骤:

https://www.npmjs.com/package/ngx-uploader

您可以从上述链接获取所有导入参数和类。

这是我的角度代码:

if (output.type === 'allAddedToQueue')  // when all files added in queue
  // uncomment this if you want to auto upload files when added
  const event: UploadInput = 
    type: 'uploadAll',
    url: API_BASE +'/api/uploads',

    method: 'POST',
    data:total_files: this.files.length.toString()
  ;
  this.uploadInput.emit(event);
 else if (output.type === 'addedToQueue'  && typeof output.file !== 'undefined')  // add file to array when added
  this.files.push(output.file);
 else if (output.type === 'uploading' && typeof output.file !== 'undefined') 
  // update current data in files array for uploading file
  const index = this.files.findIndex(file => typeof output.file !== 'undefined' && file.id === output.file.id);
  this.files[index] = output.file;

 else if (output.type === 'removed') 
  // remove file from array when removed
  this.files = this.files.filter((file: UploadFile) => file !== output.file);
 else if (output.type === 'dragOver') 
  this.dragOver = true;
 else if (output.type === 'dragOut') 
  this.dragOver = false;
 else if (output.type === 'drop') 
  this.dragOver = false;
else if (output.type === 'done')  

  if (output.file.response.status == 200)  
    var uploaded_files = output.file.response.data;
    this.propertyImage.push(uploaded_files);
   
  else  
    this.msgs = [];
    this.msgs.push( severity: 'error', summary: 'Error Message', detail: 'unable to upload images' );
  

在上面的输出代码中===完成,你会得到服务器端的响应(在我的例子中是 nodejs)

您可以在下面找到后端代码:

var formidable = require('formidable'),
    http = require('http'),
    util = require('util');

var form = new formidable.IncomingForm();

var src = './public/images/properties';
var dst_small = './public/images/properties/small'
var dst_medium = './public/images/properties/medium'
var validImage = false;
form.keepExtensions = true; //keep file extension
form.uploadDir = src;
form.onPart = function (part) 
    if (!part.filename || part.filename.match(/\.(jpg|jpeg|png)$/i)) 
        validImage = true;
        this.handlePart(part);
    

    else 
        validImage = false;
        return res.json( status: 404, msg: part.filename + ' is not allowed.' );

    

form.parse(req, function (err, fields, files) 
    if (validImage) 

        var image = files.file.path.split("/")[3];
        var name = files.file.path.split("/")[3];


        easyimg.rescrop(
            src: files.file.path, dst: dst_small + '/' + files.file.path.split('/')[3],
            width: 100, height: 100,
            cropwidth: 100, cropheight: 100,
            x: 0, y: 0
        ).then(
            function (image) 
                //  console.log('Resized and cropped: ' + image.width + ' x ' + image.height);
            ,
            function (err) 
                //  console.log(err);
            
            );


        // for largeImage
        easyimg.rescrop(
            src: files.file.path, dst: dst_medium + '/' + files.file.path.split('/')[3],
            width: 300, height: 300,
            cropwidth: 300, cropheight: 300,
            x: 0, y: 0
        ).then(
            function (image) 
                //  console.log('Resized and cropped: ' + image.width + ' x ' + image.height);
                return res.json( status: 200, msg: 'Uploaded images', data: image );

            ,
            function (err) 
                console.log(err);
            
            );
     else 
        return res.json( status: 500, msg: constant.message.error_profile_pic_type );
    
);

请根据您的文件路径更改您的图像路径。我已经使用了这段代码,它对我有用。

希望以上代码对你有所帮助。

谢谢!!

【讨论】:

问我是否有人对上面的集成有问题。 不确定我是否喜欢这个答案,因为它涉及使用上传器进行拖放。 OP 在他们的问题中没有提到上传文件,所以使用这个库似乎有点矫枉过正,劫持它来代替不以上传为中心的东西似乎是错误的做法。【参考方案4】:

这是 Angular 7 的解决方案:

Material (https://material.angular.io/) 完美地解释了它(您必须采用 >= 7.1 版本)。这是API 的链接。

首先,在你的模块中导入“DragAndDrop”模块:

import DragDropModule from '@angular/cdk/drag-drop';

然后您只需将“cdkDrag”指令添加到您的 HTML 元素:

<div class="example-box" cdkDrag>
  Drag me around
</div>

Stackblitz(来自材料): here

它真的很容易使用,如果您需要进行更具体的拖放(例如使用位置锁定),还有一些有趣的选项!

【讨论】:

【参考方案5】:

简单但功能最强大的软件包

支持角度版本 >= 4.x

为documentation

为demo

如何使用?

安装

// if you use npm
npm install angular2-draggable

// or if you use yarn
yarn add angular2-draggable

导入

import  AngularDraggableModule  from 'angular2-draggable';

@NgModule(
  imports: [
    ...,
    AngularDraggableModule
  ],
)
export class AppModule  

最后使用

// Basic Usage
<div ngDraggable>Drag Me!</div>

【讨论】:

这是真的,它很简单,也很强大。 这真是太棒了!容易,德拉古拉也是如此!检查他们两个。 拖动 SVG 元素在 chrome 中有效,但在 IE 中无效,除此之外,它非常好 该软件包已被弃用,适用于 Angular 7+ github.com/bmartinson/ngx-draggable-dom【参考方案6】:

使用 drop 事件。这只会在您删除文件时触发。

【讨论】:

我确实使用了 drop 事件,当我放下时它不会触发任何东西。【参考方案7】:

这就是我让它工作的方式。 preventDefault() 函数抛出错误,将其更改为 return false 工作正常。谢谢大家的及时回复。

 drag(channel) 
    console.log(channel);
  
  onDragOver(channel: any) 
    console.log("Drag Over");
    return false;
  
  onDrop(e:any) 
    console.log("Drop");
  

【讨论】:

以上是关于使用 Angular 4 拖放 HTML 5的主要内容,如果未能解决你的问题,请参考以下文章

HTML5拖放-当Angular移动或删除源元素时不会触发“dragend”

使用 angular4 的拖放事件在 IE11 中不起作用

拖放图片上传,角度4

错误类型错误:无法读取 Angular 7 拖放中未定义的属性“长度”

Angular 7 拖放 - 动态创建拖放区

如何在两个组件之间使用Angular7(角度材料)拖放