Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drag and Drop for changing parent-child relationship #155

Open
Chethan-7 opened this issue Jun 28, 2022 · 14 comments
Open

Drag and Drop for changing parent-child relationship #155

Chethan-7 opened this issue Jun 28, 2022 · 14 comments

Comments

@Chethan-7
Copy link

Hi,

Does the current plugin support drag-and-drop feature where i could drag a node and drop it on another node and dragged node becomes the child?
I am looking for some pointers if this is already explored.

Thanks,
Chethan

@bumbeishvili
Copy link
Owner

No, it does not currently support it, but it’s planned for the future

@surajbabar
Copy link

Any update on when this will be available?
If it is already can you share more details on how to enable it ?

@bumbeishvili
Copy link
Owner

I don't expect it to be implemented in the near future (at least for the next 4-6 months)

@A7medMo7ammed20
Copy link

Any Updates?

@bumbeishvili
Copy link
Owner

bumbeishvili commented Oct 14, 2023

@A7medMo7ammed20 there is a potential partnership opportunity for paying for the implementation of drag-drop functionality.

So there is a chance (20-30%) that it might get implemented within the next 3 months

@joelcoxokc
Copy link

@bumbeishvili I am able to contribute to this effort.
We need this feature ASAP.

@joelcoxokc
Copy link

joelcoxokc commented Oct 15, 2023

@A7medMo7ammed20

Until they get this feature in place..

I am doing this..

You still have to handle hiding the children and the edges. But this is the beginning of getting a node to drag

I do this right after I call chart.render()

const state = this.chart.getChartState();
let dragStartX: number;
let dragStartY: number;
let newParent: GenNodeData | null;
const nodesSelection = state['nodesWrapper']
.selectAll('g.node')
.on('mouseover', (d: Event, n: GenNodeData) => {
    newParent = n;
})
.on('mouseout', (d: Event, n: GenNodeData) => {
    newParent = null;
})
.call(
    d3
        .drag()
        .on('start', (d) => {
            const width = d.subject.width;
            const half = width / 2;
            const x = d.x - half;
            dragStartX = x;
            dragStartY = parseFloat(d.y);
        })
        .on('drag', function (d) {
            const g = d3.select(this);
            dragStartX += parseFloat(d.dx);
            dragStartY += parseFloat(d.dy);
            g.attr('transform', 'translate(' + dragStartX + ',' + dragStartY + ')');
        })
        .on('end', (d) => {
            console.log({ newParent });
        })
);

@bumbeishvili
Copy link
Owner

There is a #307 PR if you want to have a look and make it work.

The work I plan to do with Drag & drop is not quick and it's quite substantial, so won't merge or add anything related to this meantime

@joelcoxokc
Copy link

Here is my drag example.. I copied what I could from our production app.
https://stackblitz.com/edit/js-bmyjfc?file=index.html

This has undo/redo/cancel built into it.
Also each node can be draggable or droppable.

I made a button to start the drag process.. otherwise there are all kinds of issues when trying to pan while dragging is enabled.
So you have to click organize to start the drag-drop.

@bumbeishvili Feel free to fork this and add it to the examples

@bumbeishvili
Copy link
Owner

Nice, I'd implement it differently but good to have it implemented anyway

@joelcoxokc
Copy link

Nice, I'd implement it differently but good to have it implemented anyway

What would you do differently I would love to know as we are using this in production

@bumbeishvili
Copy link
Owner

First I am very much impressed that you implemented drag & drop without modifying source code (and I am also proud too because it's possible)

• I'd try to overcome the need to have a drag functionality dependent on the button (and it's not an easy )
• I'd build dragging functionality inside the chart and I'd expose some methods for controlling how you want the behavior of the org chart to be, specifically I'd have following methods exposed

onDragStart,   // Styling dragging node
onDrag, 
onDragEnd,  // Unstiling dragging node
onTarget(({fromData,toData,fromId,toId,fromNode,toNode})),   // Styling target node 
outTarget(({fromData,toData,fromId,toId,fromNode,toNode})),  // Unstyling target node
onNodeDrop({idFrom,idTo,nodes}=>{}) // changing the data and rendering the graph

• I'd make it possible to drop over the node once it touches another node

That said, again, your implementation is quite good since it is done without modifying anything in the core codebase and in theory will not interfere with future updates and in a way it's safe solution

@joelcoxokc
Copy link

joelcoxokc commented Jan 19, 2024

First I am very much impressed that you implemented drag & drop without modifying source code (and I am also proud too because it's possible)

• I'd try to overcome the need to have a drag functionality dependent on the button (and it's not an easy ) • I'd build dragging functionality inside the chart and I'd expose some methods for controlling how you want the behavior of the org chart to be, specifically I'd have following methods exposed

onDragStart,   // Styling dragging node
onDrag, 
onDragEnd,  // Unstiling dragging node
onTarget(({fromData,toData,fromId,toId,fromNode,toNode})),   // Styling target node 
outTarget(({fromData,toData,fromId,toId,fromNode,toNode})),  // Unstyling target node
onNodeDrop({idFrom,idTo,nodes}=>{}) // changing the data and rendering the graph

• I'd make it possible to drop over the node once it touches another node

That said, again, your implementation is quite good since it is done without modifying anything in the core codebase and in theory will not interfere with future updates and in a way it's safe solution

I need to implement the same thing in another interface in our app..
Depending on complexity, I will try to implement this in the core library and send you a PR

  • Regarding when the node touches another node...
    I tried to achieve this best I could, but the dragging node could be touching between 1 and three nodes, based on node margin.
    So I implemented to when the dragging node is more that 50% over the drop on both x & y, I highlight the node

I could probably do (50% - nodeMargin)

  • Regarding drag without a button. It is definitely possible, you just have to remove the check on the drag().filter()
    However, since we are using this on mobile. Most of the tree takes up a mobile screen. I couldn't find a way to determine whether the user was trying to drag a node or pan the screen.
    I did consider doing a long-press to start dragging, which would be cool

@joelcoxokc
Copy link

@bumbeishvili #350

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants