Angular Material,cdk, Drag & Drop, dropping, and inserting into current position of TextArea Field

Angular Material,cdk, Drag & Drop, dropping,and inserting into current position of TextArea Field

我正在检查这些示例:

https://jsfiddle.net/qskxzh0e/3/
http://jsfiddle.net/3p1nra6m/1/
https://stackblitz.com/edit/angular-component-drag

https://material.angular.io/cdk/drag-drop/overview

可以插入(不替换所有包含的文本)一些 Token 形式的列表作为 cdkDropListDroppedcdkDrag?

我已经解决了我之前的问题,因为我可以在 Textarea 中插入,而且我有新的挑战,这里是我的 stackblitz 代码(抱歉颜色和闪烁,因为我是测试方法):

对于这段代码,我实现了一个接口:

export interface EntryKeyValue {
  key: string;
  value: string;
}

在我的组件中,我有一个像这样的数组:

  ekvs: EntryKeyValue[] = [
    {
      key: 'first',
      value: 'First Item'
    },
    {
      key: 'second',
      value: 'Second Item'
    },
    {
      key: 'third',
      value: 'Third Item'
    },
  ];

在我的 HTML 中,我想显示 key 属性,但在我的文本区域中,我想插入 value 属性。

例如:我应该显示 'third',但我应该在我的文本区域中插入 'Third Item'

怎么做?

在我的 app.module.ts 文件的 imports 数组中,我注释了 //, DragDropModule 因为 *cdkDragPreview 没有显示!为了让用户知道插入的最终值是什么。但是我的方法并没有像右下角显示的那样起作用!!!

它与我的方法 DragDropModule 兼容吗?如何同时使用两者?

使用 textarea 时,最好使用 HTML5 Drag and Drop API,这正是您在演示中使用的。

使用 Angular CDK 拖放功能,您必须自己检测插入光标在 textarea 中的位置。

如果您想显示一个值但插入另一个值,您需要将所需的值传递给 DataTransfer.setData() 方法。

只需在拖动元素上添加一些属性

<div 
  class="example-box"
  ...
  [attr.data-drag-data]="ekv.value"

现在您可以从 ts 代码中读取该值

event.dataTransfer.setData('text/plain', event.target.dataset.dragData);

Forked Stackblitz

更新

为了自定义 HTML5 d&d 预览,您可以使用 DataTransfet.setDragImage() 方法

public dragstart_handler(event: any) {
  const preview = event.target.cloneNode(true);
  // store it for element so that we can remove it from DOM later on
  event.target.preview = preview;  
  preview.className = 'preview';
  preview.style.cssText = `position: absolute; top: -100%; left: -100%;
                           width: ${event.target.offsetWidth}px; `;
  document.body.appendChild(preview);
  event.dataTransfer.setDragImage(preview, 0, 0);
...
public dragend_handler(event: any) {
  event.target.preview.parentNode.removeChild(event.target.preview);

Updated Stackblitz

查看这篇文章: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/data-* 为了添加您的自定义属性并在您的模态组件中使用它们。

在您的 HTML 模板中添加:[attr.data-value]="ekv.value" 在带有 drabggable="true"

的 div 内
  <div 
    class="example-box"
    draggable="true"
    (drag)="drag_handler($event)"
    (dragend)="dragend_handler($event)"
    (dragenter)="dragenter_handler($event)"
    (dragleave)="dragleave_handler($event)"
    (dragover)="dragover_handler($event)"
    (dragstart)="dragstart_handler($event)"
    (drop)="drop_handler($event)"
    [attr.data-value]="ekv.value"
    *ngFor="let ekv of ekvs" cdkDrag
    >
      <div>
        <p *cdkDragPreview><span class="blink preview">{{ekv.value}}</span></p>
      </div>
      <div class="example-custom-placeholder" *cdkDragPlaceholder></div>
      {{ekv.key}}
  </div>

为了添加预览,我更改了样式,例如:

在您的 Modal 组件中,将您的 dragstart_handler method 编辑为:

  public dragstart_handler(event: any) {
    
    const crt = event.target.cloneNode(true);

    crt.style.backgroundColor = "#D1F8D1";
    crt.style.color = "darkred";
    crt.style.position = "absolute";
    crt.style.borderWidth = "initial";
    crt.style.borderStyle = "dashed";
    crt.style.borderColor = "blue";
    crt.style.top = "-1000px";
    crt.className += " blink";
    crt.style.right = "0px";
    crt.innerText = event.target.dataset.value;
    document.body.appendChild(crt);
    event.dataTransfer.setDragImage(crt, 0, 0);
    //event.dataTransfer.setData('text/plain', event.target.innerText);
    event.dataTransfer.setData('text/plain', event.target.dataset.value);
    document.getElementById("paragraph2").innerHTML = "Paragraph2: Starting dragging the <span style='color:red'>" + event.target.innerText + "</span> element.";
  }

也检查此 post:https://web.dev/drag-and-drop/