-
I have a list of sortable containers, supposedly, each one of these containers would also allow for components to be inside of them. The problem is that I have the "insert component" functionality somewhere else other than in the direct descendance of said <DndContext>
<Sidebar />
<Board />
</DndContext/> With the <DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
<SortableContext items={containersIds} strategy={verticalListSortingStrategy}>
{containersIds.map((id) => (
<Container key={id} id={id} />
))}
</SortableContext>
</DndContext> This All of this visualized, if we assume the "A" icon (which is an So, once that's dropped, we'd have: I think this best represents what I'm trying to achieve: https://www.youtube.com/watch?v=eDcGNrc0y5U&t=25m11s - if you notice the blue stroke, that's actually a container, well, that interface has a "+" sign on the top. If you click that, it allows you to add a component within the container. What happened here is that a draggable from the outside communicated with a droppable very far away from it (in terms of the dom). As it currently stands, whenever I drag the "A" over a container, absolutely nothing happens. It sees the drag, sure, but it doesn't see what it is over. A possibility would be to just simply put Any way to achieve this? Edit: I just realized the implications of what I asked. Is there a reason for why the whole architecture wasn't built around "here are containers that you can drop stuff into, you decide what drops and where", because having a central store-like entity to manage all these interactions would basically allow free movement of data and make any complex interactions really simple. Would definitely be nice if you could share some details as to why some big choices were made during development! :) |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 5 replies
-
Hey @growthwp, thanks for the detailed post and for adding visual supports to illustrate. This library is currently in beta, and this kind of feedback is definitely welcome to understand some of the use-cases that are stretching the current architecture of library. To answer your question, I don't foresee it being possible to accept draggables that come from outside of a parent
I agree that this solution isn't optimal from a separation of concerns perspective. However, a lot of the pieces you mention are deeply interconnected, and are hard to neatly separate. In an ideal world, this use-case could perhaps one day be modeled as something that looks a bit more like this: <DndContext>
<DndConfig sensors={sidebarSensors} collisionDetection={sidebarCollisionDetectionStrategy}>
<Sidebar />
</DndConfig>
<DndConfig sensors={boardSensors} collisionDetection={boardCollisionDetectionStrategy}>
<Board />
</DndConfig>
</DndContext> And within function Board() {
useDndMonitor({
onDragEnd() {
// Handle drop logic that is board specific
}
});
} There's a lot of work that would need to happen under the hood to support this type of setup however, and in the short term, there are higher priority tasks that need to be worked on. For the time being, your use-case can be achieved by conditionally changing the configuration of your collision detection, sensors and Something like: function App() {
const [activeId, setActiveId] = useState(null);
const [sidebarItems] = useState(["sidebar-A", "sidebar-B"]);
const [boardItems, setBoardItems] = useState(["board-1", "board-2"]);
const collisionDetection = isSidebarItem(activeId)
? sidebarCollisionDetectionStrategy
: boardCollisionDetectionStrategy;
return (
<DndContext
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
collisionDetection={collisionDetection}
>
<Sidebar items={sidebarItems} />
<Board />
</DndContext>
);
function handleDragStart({ active }) {
setActiveId(active.id);
}
function handleDragEnd({ active, over }) {
if (over && over.id !== active.id) {
if (isBoardItem(active.id)) {
setBoardItems((items) =>
arrayMove(items, items.indexOf(active.id), items.indexOf(over.id))
);
} else if (isSidebarItem(active.id) && isBoardItem(over.id)) {
setBoardItems((items) =>
[...items, active.id],
)
}
setActiveId(null);
}
}
}
function isSidebarItem(id) {
return id.includes("sidebar");
}
function isBoardItem(id) {
return id.includes("board");
} Again, I recognize this really doesn't lead to a nice separation of concerns for large complex apps. There's active discussions on how some folks have solved this in their own apps happening in this thread, feel free to contribute to that discussion as it will help inform the future direction of the library with regards to providing consumers with primitives to achieve a better separation of concerns. |
Beta Was this translation helpful? Give feedback.
Hey @growthwp, thanks for the detailed post and for adding visual supports to illustrate.
This library is currently in beta, and this kind of feedback is definitely welcome to understand some of the use-cases that are stretching the current architecture of library.
To answer your question, I don't foresee it being possible to accept draggables that come from outside of a parent
<DndContext>
. There's a host of reasons why this wouldn't work. However, I think there are other strategies that could be implemented that would allow for a better separation of concerns, which ultimately is what I think you are looking for. More on that below.