【问题标题】:How to make a draggable and droppable div also editable?如何使可拖放的 div 也可编辑?
【发布时间】:2023-02-09 18:30:34
【问题描述】:

我正在使用 dnd-kit/core 并且无法通过编辑按钮使我的 UserComponent 可编辑。我不认为我写的编辑按钮可能与 dnd-kit 兼容(因为它不起作用)?任何提示或解决方案将不胜感激!!

谢谢。

import React, { useState, useEffect } from 'react';
import { closestCenter, DndContext, PointerSensor, useSensor } from '@dnd-kit/core';
import { arrayMove, SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable';
import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';



const UserComponent = ({
  id,
  body
}) => {
  const [isEditing, setIsEditing] = useState(false);

  const toggleEditing = () => {
    setIsEditing(!isEditing);
  };

  const handleBlur = () `your text`=> {
    setIsEditing(false);
  };

  const {
      setNodeRef,
      attributes,
      listeners,
      transition,
      transform,
      isDragging,
  } = useSortable({ id: id })

  const style = {
      transition,
      transform: CSS.Transform.toString(transform),
      border: '2px solid black',
      marginBottom: 5,
      marginTop: 5,
      display: "block",
      opacity: isDragging ? 0.5 : 1,
  }

  return (
      <>
      <div
          ref={setNodeRef}
          {...attributes}
          {...listeners}
          style={style}
      >
        <button onClick={toggleEditing}>Edit</button>
        <div
          contentEditable={isEditing}
          onBlur={handleBlur}
          suppressContentEditableWarning
        >
          {body}
        </div>
      </div>
      
     </>
  )
}

function DragApp() {

  const [items, setItems] = useState([
      {
        id: "1",
        name: "Manoj"
      },
      {
        id: "2",
        name: "John"
      },
      {
        id: "3",
        name: "Ronaldo"
      },
      {
        id: "4",
        name: "Harry"
      },
      {
        id: "5",
        name: "Jamie"
      }
    ])

  useEffect(() => {
      fetch('https://jsonplaceholder.typicode.com/posts')
        .then((response) => response.json())
        .then((data) => setItems(data));
    }, []);

const sensors = [useSensor(PointerSensor)];

const handleDragEnd = ({active, over}) => {
  if (active.id !== over.id) {
    setItems((items) => {
      const oldIndex = items.findIndex(item => item.id === active.id)
      const newIndex = items.findIndex(item => item.id === over.id)

      return arrayMove(items, oldIndex, newIndex)
    })
  }
}

return (
  <div
    style={{
      margin: 'auto',
      width: 1000,
      textAlign: 'center',

    }}
  >
    <DndContext
      sensors={sensors}
      collisionDetection={closestCenter}
      onDragEnd={handleDragEnd}
    >
      <SortableContext
        items={items.map(item => item.id)}
        strategy={verticalListSortingStrategy}
      >
        {
          items.map(
            item => <UserComponent {...item} key={item.id} />
          )
        }
      </SortableContext>
    </DndContext>
  </div>
);
}

export default DragApp;

我尝试了上面的代码并希望编辑按钮使每个 div 都可以编辑 - 每个编辑按钮都特定于 div。

实际结果是文本通过,我可以拖放 div,但 div 不可编辑,编辑按钮不可单击。

【问题讨论】:

    标签: reactjs contenteditable dnd-kit


    【解决方案1】:

    你应该添加两件事:

    1. 在 isEditing 状态添加“disabled: true”以使用 Sortable 属性(当您编辑文本时它将停止拖动):
        const {
          setNodeRef,
          attributes,
          listeners,
          transition,
          transform,
          isDragging,
        } = useSortable({ id: id, disabled: isEditing && true });
      
      1. 覆盖传感器的激活器功能,制作新的:
      class MyPointerSensor extends PointerSensor {
        static activators = [
          {
            eventName: "onPointerDown",
            handler: ({ nativeEvent: event }) => {
              if (
                !event.isPrimary ||
                event.button !== 0 ||
                isInteractiveElement(event.target)
              ) {
                return false;
              }
      
              return true;
            },
          },
        ];
      }
      
      function isInteractiveElement(element) {
        const interactiveElements = [
          "button",
          "input",
          "textarea",
          "select",
          "option",
        ];
      
        if (interactiveElements.includes(element.tagName.toLowerCase())) {
          return true;
        }
      
        return false;
      }
      

      它将使按钮、输入和文本区域成为不可拖动的元素。

      然后将传感器更换为新传感器:

        const sensors = [useSensor(MyPointerSensor)];
      

      你可以在这里获得更多信息:How do I prevent draggable on input and btns

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-14
      相关资源
      最近更新 更多