I am very new to react.js and JavaScript, so apologies in advance. I am trying to make a very concise diagramming tool in my webpage, where the user can create their own use case diagram.
I am looking at these examples:
https://reactflow.dev/examples/drag-and-drop/
https://reactflow.dev/examples/update-node/
I got the drag and drop to work, but am having a hard time applying the update node feature. My final goal is to let the user select a node, and update its name via input at the sidebar.
I started with adding const onElementClick = (event, element) => event.dataTransfer.getData("label"); to the main file to get the label from the sidebar, and am trying to send back the changed label by adding the block code below.
<label> label: </label>
<input value={nodeName} onChange={(evt) => setNodeName(evt.target.value)} />
Because their example on https://reactflow.dev/examples/update-node/ has everything in a single file, and am not able to update the node's name with selection, I am just a bit unsure how to proceed from here.
Any help would be sincerely appreciated, as a beginner in react. Again, apologies and thanks in advance!
main.js
import Sidebar from "./Sidebar";
const initialElements = [
{
id: "1",
type: "input",
data: { label: "User" },
position: { x: 300, y: 150 },
},
{
id: "2",
type: "default",
data: { label: "Use Case" },
position: { x: 700, y: 250 },
},
{
id: "3",
type: "output",
data: { label: "Database" },
position: { x: 1100, y: 350 },
},
];
let id = 0;
const getId = () => `dndnode_${id++}`;
export const Tester = () => {
const reactFlowWrapper = useRef(null);
const [reactFlowInstance, setReactFlowInstance] = useState(null);
const [elements, setElements] = useState(initialElements);
const [nodeName, setNodeName] = useState("Node 1");
const [nodeBg, setNodeBg] = useState("#eee");
const [nodeHidden, setNodeHidden] = useState(false);
const onElementClick = (event, element) => event.dataTransfer.getData("click", element);
const onConnect = (params) => setElements((els) => addEdge(params, els));
const onElementsRemove = (elementsToRemove) =>
setElements((els) => removeElements(elementsToRemove, els));
const onLoad = (_reactFlowInstance) => setReactFlowInstance(_reactFlowInstance);
const onDragOver = (event) => {
event.preventDefault();
event.dataTransfer.dropEffect = "move";
};
const onDrop = (event) => {
event.preventDefault();
const reactFlowBounds = reactFlowWrapper.current.getBoundingClientRect();
const type = event.dataTransfer.getData("application/reactflow");
const label = event.dataTransfer.getData("label");
const position = reactFlowInstance.project({
x: event.clientX - reactFlowBounds.left,
y: event.clientY - reactFlowBounds.top,
});
const newNode = {
id: getId(),
type,
position,
data: { label: label },
};
setElements((es) => es.concat(newNode));
};
return (
<div className="dndflow">
<ReactFlowProvider>
<Box
className="reactflow-wrapper"
ref={reactFlowWrapper}
style={{ height: 600 }}
sx={{ display: "flex", justifyContent: "space-between", justifyContent: "center" }}
>
<ReactFlow
elements={elements}
onConnect={onConnect}
onElementsRemove={onElementsRemove}
onLoad={onLoad}
onDrop={onDrop}
onDragOver={onDragOver}
onElementClick={onElementClick}
>
<Controls />
<MiniMap />
<Background variant="lines" size={1.5} gap={20} color="#eee" />
</ReactFlow>
<Box sx={{ ml: 10 }}>
<Sidebar />
</Box>
</Box>
</ReactFlowProvider>
</div>
);
};
Sidebar.js
export default () => {
const onDragStart = (event, nodeType, label) => {
event.dataTransfer.setData("application/reactflow", nodeType);
event.dataTransfer.setData("label", label);
event.dataTransfer.effectAllowed = "move";
};
const changeNodeName = (event, nodetype, label) => {
//event.dataTransfer.getData()
const [nodeName, setNodeName] = useState("Node 1");
};
return (
<aside>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
}}
>
<div className="description">Drag nodes to the pane.</div>
<Box
className="dndnode input"
onDragStart={(event) => onDragStart(event, "input", "User")}
draggable
sx={{
mt: 2,
border: 1,
borderColor: "blue",
borderRadius: 0.5,
width: 200,
height: 50,
textAlign: "center",
py: 1.4,
"&:hover": {
opacity: 0.5,
},
}}
>
User
</Box>
<Box
className="dndnode"
onDragStart={(event) => onDragStart(event, "default", "Use Case")}
draggable
sx={{
mt: 2,
border: 0.5,
borderColor: "black",
borderRadius: 0.5,
width: 200,
height: 50,
textAlign: "center",
py: 1.4,
"&:hover": {
opacity: 0.5,
},
}}
>
Use Case
</Box>
<Box
className="dndnode output"
onDragStart={(event) => onDragStart(event, "output", "Database")}
draggable
sx={{
mt: 2,
border: 0.5,
borderColor: "red",
borderRadius: 0.5,
width: 200,
height: 50,
textAlign: "center",
py: 1.4,
"&:hover": {
opacity: 0.5,
},
}}
>
Database
</Box>
</Box>
</aside>
);
};