<div contentEditable>
<svg viewBox='0 0 300 300'>
<text x=2 y=40>
Can this be a text input field?
</text>
<text y=80>
But not this
</text>
<text y=110>
And not this
</text>
</svg>
</div>
The text in the above SVG is editable because it is wrapped in <div contentEditable>
, however for our use case this is not ideal as is:
- most importantly, we are using React and we'd like the editable text to be controlled in state.
- all text in the above SVG is editable, not just the first text field as is desired
- it is a big buggy, with the cursor going way far to the right
It is possible to create an individually controlled (with React useState
) SVG text field?
EDIT: something along these lines does appear to work:
const [test, setTest] = useState('here is some text');
// And Return
return (<>
<svg>
<foreignObject x="40" y="40" width="300" height="150">
<div xmlns="http://www.w3.org/1999/xhtml">
<FormControl
className='modal-input'
type='text'
value={test}
onChange={(e) => setTest(e.target.value)}
name='firstname'
placeholder='First Name'
/>
</div>
</foreignObject>
...
Where FormElement
is from react-bootstrap. We are going to keep working with this and see if it fits our use case fully, but so far, so good!
CodePudding user response:
You can embed HTML fragments (including React portals for example) in SVG using the <foreignObject>
tag (which is specifically designed to allow HTML in SVG). BTW I think if you just want to embed some inputs into SVG, doing it using contenteditable
does not seem to make any sense. Just use normal <inputs>
<svg viewBox='0 0 300 300'>
<foreignObject x='0' y='0' width='100' height='100'>
<div contenteditable>
Can this be a text input field?
</div>
</foreignObject>
<text y='80'>
But not this
</text>
<text y='110'>
And not this
</text>
</svg>