Angular Material、cdk、拖放、拖放和插入到 TextArea 字段的当前位置

Posted

技术标签:

【中文标题】Angular Material、cdk、拖放、拖放和插入到 TextArea 字段的当前位置【英文标题】:Angular Material,cdk, Drag & Drop, dropping,and inserting into current position of TextArea Field 【发布时间】:2021-12-06 18:59:17 【问题描述】:

我正在检查这些示例:

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 属性,但在我的 Textarea 中我想插入 value 属性。

例如:我应该显示 'third',但我应该在我的 textarea 中插入 'Third Item'

怎么做?

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

DragDropModule 是否与我的方法兼容?以及如何同时使用这两种方法?

【问题讨论】:

stackblitz.com/edit/angular-yhfiqn?file=app%2Fapp.component.ts jsfiddle.net/3p1nra6m/1 github.com/angular/components/issues/9979 stackblitz.com/angular/… 查看此答案***.com/a/27990218/1410223 和此帖子:kryogenix.org/code/browser/custom-drag-image.html 【参考方案1】:

使用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.offsetWidthpx; `;
  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

【讨论】:

感谢您的帮助。但是,我怀疑如何启用 Preview HTML5 Drag And Drop 替换 *cdkDragPreview? @Anita 我扩展了我的答案 previewevent.target.preview中使用时是任意属性吗?根据文档,它不是属性。 @Anita 是的,这只是我的自定义任意属性。我使用它来存储对该属性将获取并从 DOM 中删除的元素的引用【参考方案2】:

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

在您的 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.";
  

也请查看此帖子:https://web.dev/drag-and-drop/

【讨论】:

以上是关于Angular Material、cdk、拖放、拖放和插入到 TextArea 字段的当前位置的主要内容,如果未能解决你的问题,请参考以下文章

Angular Material、cdk、拖放、拖放和插入到 TextArea 字段的当前位置

Angular 嵌套拖放 / CDK 材质 cdkDropListGroup cdkDropList nested

在 Angular Material CDK 拖放中,如何防止项目随着元素移动而自动重新排列?

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

Angular CDK 拖放:不要移动源项目

重新实例化数据时,Angular CDK 拖放列表会中断