【问题标题】:HTML 5 Drag & Drop with Angular 4使用 Angular 4 拖放 HTML 5
【发布时间】: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 }}" alt="{{ channel.channel }}" width="100" height="100">
          <img class="img-rounded" src="{{ channel.compChannel.compChannelLogo }}" alt="{{ channel.channel.compChannelName }}" width="100" height="100">
        </ng-container>
        <ng-template #noCompChannel>
          <img class="img-rounded" src="{{ channel.logo }}" alt="{{ channel.channel }}" 
          width="100" height="100" >
        </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 }}" alt="{{ channels[0].channel }}" width="70" height="70">
      <img class="img-rounded" src="{{ channels[0].compChannel.compChannelLogo }}" alt="{{ channels[0].compChannel.compChannelName }}"
        width="70" height="70">
    </ng-container>
    <ng-template #noCompChannel>
      <img class="img-rounded" src="{{ channels[0].logo }}" alt="{{ channels[0].channel }}" width="70" height="70">
    </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 根本不触发。

标签: html angular typescript drag-and-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"
      width="88" 
      height="31">
</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");
        }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-02
        相关资源
        最近更新 更多