Some components have a popper element which displays the slotted elements in a portal (a different place in the DOM). The ld-context-menu component and the ld-tooltip component are examples of such components. In order to keep all event listeners attached and working, the components move the original element including all the attached event listeners to the popper element.
In some cases this behavior can be problematic. For instance: If you are using a UI library which renders elements based on state (such as React or Vue) and have a conditionally rendered element as a direct child of a component that moves the Node
to a different place in the DOM, you may run into the error:
Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
The current workaround is to wrap the conditionally rendered element in another element.
export default function App() {
const tetherOptions = {
bodyElement: document.getElementById('root')
}
const [checked, setChecked] = useState(true)
return (
<>
<LdButton onClick={() => { setChecked(!checked) }}>Toggle checked</LdButton>
<LdTooltip arrow tetherOptions={tetherOptions as any} triggerType="click">
{checked && <span>🤓</span>}
</LdTooltip>
</>
);
}
export default function App() {
const tetherOptions = {
bodyElement: document.getElementById('root')
}
const [checked, setChecked] = useState(true)
return (
<>
<LdButton onClick={() => { setChecked(!checked) }}>Toggle checked</LdButton>
<LdTooltip arrow tetherOptions={tetherOptions as any} triggerType="click">
<div>
{checked && <span>🤓</span>}
</div>
</LdTooltip>
</>
);
}