Pha*_*aki 8 html javascript popover reactjs treeviz-react
我正在尝试制作一个具有 Treeviz 依赖项的 Web 应用程序。目标是在树的每个节点上放置一个弹出按钮,如果用户单击该按钮,他/她可以看到该节点的描述,并且之后应该可以编辑。我尝试了很多方法,但对我来说,弹出窗口在 React 中不起作用。
有一个我想做的例子。你可以看到我必须将 React 组件插入 HTML,因为我正在使用 renderToString。您只需查看树的 renderNode 属性即可。我引用 renderNode 中的 React 组件,例如:${tooltip} ${popover}。
import React from "react";
import { TreevizReact } from "treeviz-react";
import { renderToString } from "react-dom/server";
const data_1 = [
{
id: 1,
text_1: "Chaos",
description: "Void",
father: null,
color: "#FF5722"
},
{
id: 2,
text_1: "Tartarus",
description: "Abyss",
father: 1,
color: "#FFC107"
},
{ id: 3, text_1: "Gaia", description: "Earth", father: 1, color: "#8BC34A" },
{ id: 4, text_1: "Eros", description: "Desire", father: 1, color: "#00BCD4" }
];
export const App = () => {
return (
<div style={{ marginLeft: 10 }}>
<div style={{ display: "flex" }}>
<TreevizReact
data={data_1}
relationnalField={"father"}
nodeWidth={120}
nodeHeight={80}
areaHeight={500}
areaWidth={1000}
mainAxisNodeSpacing={2}
secondaryAxisNodeSpacing={2}
linkShape={"quadraticBeziers"}
renderNode={(data) => {
const nodeData = data.data;
const settings = data.settings;
let result = "";
const tooltip = renderToString(
<strong
data-toggle="tooltip"
data-placement="top"
title={nodeData.description}
>
{nodeData.text_1}
</strong>
);
const popover = renderToString(
<button
type="button"
className="btn btn-secondary"
data-container="body"
data-toggle="popover"
data-placement="top"
data-content={nodeData.description}
>
Popover on top
</button>
);
if (data.depth !== 2) {
result = `<div className="box"
style='cursor:pointer;height:${settings.nodeHeight}px; width:${settings.nodeWidth}px;display:flex;flex-direction:column;justify-content:center;align-items:center;background-color:${nodeData.color};border-radius:5px;'>
<div>
${tooltip}
${popover}
</div></div>`;
} else {
result = `<div className="box" style='cursor:pointer;height:${
settings.nodeHeight
}px; width:${
settings.nodeHeight
}px;display:flex;flex-direction:column;justify-content:center;align-items:center;background-color:${
nodeData.color
};border-radius:${settings.nodeHeight / 2}px;'><div><strong>
${nodeData.text_1}
</strong></div></div>`;
}
return result;
}}
duration={600}
isHorizontal
linkWidth={(node) => 10}
/>
</div>
</div>
);
};
export default App;
Run Code Online (Sandbox Code Playgroud)
您可以尝试一下:https://codesandbox.io/s/zealous-orla-4bq5f ?file=/src/App.js
也尝试过
const popover = renderToString(
<Popup
trigger={<button> Trigger</button>}
position="right center"
>
<form onSubmit={saveHandler}>
<ContentEditable
html={text.current}
onChange={handleChange}
/>
<button type="submit">Save</button>
<button>Cancel</button>
</form>
</Popup>
Run Code Online (Sandbox Code Playgroud)
const popoverContent = (
<Popover id="popover-basic">
<Popover.Header as="h3">Popover right</Popover.Header>
<Popover.Body>
And here's some <strong>amazing</strong> content. It's very
engaging. right?
</Popover.Body>
</Popover>
);
const popover = renderToString(
<OverlayTrigger
trigger="click"
placement="right"
overlay={popoverContent}
>
<Button variant="success">Click me to see</Button>
</OverlayTrigger>
);
Run Code Online (Sandbox Code Playgroud)
他们都不为我工作。
您的方法可能不起作用,因为树中的 dom 元素是动态创建的,并且bootstrap 不会设置它们。
一种更具反应性的方法是使用react-bootstrap lib并管理状态中的每个UI方面。为了实现工具提示,该Overlay组件实际上是一个名为 target 的 prop,它允许您更改工具提示显示的元素。
<Overlay target={tooltipTarget} show={showTooltip} placement="right">
{(props) => (
<Tooltip id="overlay-example" {...props}>
{tooltipNode?.data.text_1}
</Tooltip>
)}
</Overlay>
Run Code Online (Sandbox Code Playgroud)
然后你只需要在组件中管理所有这些状态onNodeMouseEnter和处理程序。onNodeMouseLeaveTreevizReact
onNodeMouseEnter={(_event, node) => {
const t = document.querySelector(`#node-${node.id}`);
setTooltipTarget(t);
setShowTooltip(true);
setTooltipNode(node);
}}
onNodeMouseLeave={(_event, node) => {
setTooltipTarget(null);
setShowTooltip(false);
setTooltipNode(null);
}}
Run Code Online (Sandbox Code Playgroud)
弹出窗口与另一组状态遵循相同的逻辑。
<div ref={ref}>
<Overlay
show={!!selectedNode.current}
target={target}
placement="bottom"
container={ref.current}
containerPadding={20}
>
<Popover id="popover-contained">
{/* hack to avoid weird blinking (due mutable state) */}
{!!selectedNode.current && (
<>
some form based on node data
{JSON.stringify(selectedNode.current?.data)}
</>
)}
</Popover>
</Overlay>
</div>
Run Code Online (Sandbox Code Playgroud)
并在 onNodeClick 处理程序中
onNodeClick={(_event, node) => {
const t = document.querySelector(`#node-${node.id}`);
// unselect if already selected
if (selectedNode.current?.id === node.id) {
selectedNode.current = null;
setTarget(null);
} else {
selectedNode.current = node;
setTarget(t);
}
}}
Run Code Online (Sandbox Code Playgroud)
你可能会注意到这次我通过 ref ( selectedNode.current) 使用了一个可变变量,出于某种原因使用状态导致了一些问题,可能是由于 D3 和 React 具有不同的渲染周期,这就是为什么你可能会在此实现中遇到一些其他故障的原因。
https://codesandbox.io/s/quizzical-buck-slofh?file=/src/App.js
| 归档时间: |
|
| 查看次数: |
2905 次 |
| 最近记录: |