You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 5 + Dragula无法实现多层内部对象拖拽问题

Hey there, let's work through this drag-and-drop issue you've been stuck on for days! I get it—getting nested divs and string array data to play nice with drag functionality can be tricky. Let's start by breaking down the core pieces you need to fix, based on your setup (red main div, black containers, blue items).

Core Fixes for Your Drag-and-Drop Setup

1. Add Essential Drag Attributes & Event Hooks

First, your blue item divs need to explicitly be marked as draggable, and you need to hook up the 3 key drag events: dragstart, dragover, and drop (browsers block drops by default unless you override it).

Updated HTML Snippet

<!-- Red main container -->
<div class="main-container">
  <!-- Black container divs -->
  <div class="item-container" data-container-id="container-1">
    <!-- Blue draggable items -->
    <div class="item" draggable="true" data-item-text="First Item">First Item</div>
    <div class="item" draggable="true" data-item-text="Second Item">Second Item</div>
  </div>
  <div class="item-container" data-container-id="container-2">
    <div class="item" draggable="true" data-item-text="Third Item">Third Item</div>
  </div>
</div>

2. Sync Drag Actions with Your String Array Data

Since you're working with an array of objects (each holding a string array of items), you need to tie DOM drag events directly to updating this data model. Here's a TypeScript example that handles both the UI and data sync:

TypeScript Logic Example

// Your data model (match this to your actual object structure)
interface Container {
  id: string;
  items: string[];
}

// Initial data
let containers: Container[] = [
  { id: "container-1", items: ["First Item", "Second Item"] },
  { id: "container-2", items: ["Third Item"] }
];

// Track the currently dragged item
let activeDragItem: string | null = null;

// Initialize drag event listeners
function setupDragEvents() {
  // Handle drag start (mark item as dragging, store its value)
  document.addEventListener("dragstart", (e) => {
    const target = e.target as HTMLElement;
    if (target.classList.contains("item")) {
      activeDragItem = target.dataset.itemText || null;
      target.classList.add("dragging");
    }
  });

  // Clean up drag state when done
  document.addEventListener("dragend", (e) => {
    const target = e.target as HTMLElement;
    if (target.classList.contains("item")) {
      target.classList.remove("dragging");
    }
  });

  // Allow drop by preventing default browser behavior
  document.addEventListener("dragover", (e) => {
    e.preventDefault();
    const container = e.target.closest(".item-container") as HTMLElement;
    if (container) container.classList.add("drag-over");
  });

  // Remove hover state when dragging leaves a container
  document.addEventListener("dragleave", (e) => {
    const container = e.target.closest(".item-container") as HTMLElement;
    if (container) container.classList.remove("drag-over");
  });

  // Handle the drop event (update data + re-render UI)
  document.addEventListener("drop", (e) => {
    e.preventDefault();
    const targetContainer = e.target.closest(".item-container") as HTMLElement;
    if (!targetContainer || !activeDragItem) return;

    targetContainer.classList.remove("drag-over");
    const targetContainerId = targetContainer.dataset.containerId || "";

    // 1. Remove item from its original container's data
    containers = containers.map(container => {
      if (container.items.includes(activeDragItem)) {
        return { ...container, items: container.items.filter(i => i !== activeDragItem) };
      }
      return container;
    });

    // 2. Add item to the target container's data
    containers = containers.map(container => {
      if (container.id === targetContainerId) {
        return { ...container, items: [...container.items, activeDragItem] };
      }
      return container;
    });

    // 3. Re-render the UI to reflect updated data
    renderContainers();
  });
}

// Helper to re-render containers from the data model
function renderContainers() {
  const mainContainer = document.querySelector(".main-container") as HTMLElement;
  mainContainer.innerHTML = "";

  containers.forEach(container => {
    const containerDiv = document.createElement("div");
    containerDiv.className = "item-container";
    containerDiv.dataset.containerId = container.id;

    container.items.forEach(item => {
      const itemDiv = document.createElement("div");
      itemDiv.className = "item";
      itemDiv.draggable = true;
      itemDiv.dataset.itemText = item;
      itemDiv.textContent = item;
      containerDiv.appendChild(itemDiv);
    });

    mainContainer.appendChild(containerDiv);
  });
}

// Initialize everything
setupDragEvents();
renderContainers();

3. Add Styling for Clear Drag Feedback

These CSS rules will make the drag experience intuitive for users:

.main-container {
  background-color: red;
  padding: 1.5rem;
  display: flex;
  gap: 1.5rem;
}

.item-container {
  background-color: black;
  padding: 1rem;
  min-width: 180px;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  transition: border 0.2s;
}

.item {
  background-color: blue;
  color: white;
  padding: 0.75rem;
  cursor: grab;
  transition: opacity 0.2s;
}

.item.dragging {
  opacity: 0.5;
  cursor: grabbing;
}

.item-container.drag-over {
  border: 2px dashed white;
}

4. Troubleshooting Common Hiccups

  • Items won't drag: Double-check that draggable="true" is set on every blue item, and that your event listeners are properly initialized (call setupDragEvents() after the DOM loads!).
  • Drop doesn't register: Make sure you're calling e.preventDefault() in the dragover event—browsers block drops by default.
  • Data doesn't update: Verify your renderContainers function is using the latest containers array to rebuild the DOM (avoid mutating the original array directly—use spread operators like in the example).

If you're hitting a specific issue (like items disappearing after drop, or visual glitches in your screenshot), share those details and we can narrow it down further!

内容的提问来源于stack exchange,提问作者Kiho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:53:19