I'm using ReactJS to render text values into contenteditable
DOM nodes. Eg:
var data = [{
value: 'Hello '
},{
value: 'World!'
}];
var component = React.createClass({
render: function () {
var pieces = this.props.data.map(function (piece) {
return (
<span contentEditable="false">
<span contentEditable="true">{piece.value}</span>;
</span>
);
});
return <div contentEditable="true">{pieces}</div>;
}
});
React.renderComponent(<component data={data} />, someContainer);
Resulting in DOM that looks like this (for many reasons):
<div contenteditable="true">
<span contentEditable="false">
<span contentEditable="true">Hello </span>;
</span>
<span contentEditable="false">
<span contentEditable="true">World!</span>;
</span>
</div>
When a user interacts with these editable spans by, for example, backspacing from the second one into the first one, I can update the data by removing the last character from the first model, but I need to somehow tell React to position the cursor at the end of the first span[contenteditable="true"]
In my .render()
function I have a this.state.caretPosition
property telling me the position the cursor should be (this only exists on ONE component). render()
is supposed to just return a (virtual) DOM Node. How do I tell ReactJS to position the caret inside the returned DOM Node at that position?
Example: jsbin
I was able to get your example working with the methods described in these how-to-set-caretcursor-position-in-contenteditable-element-div, select-range-in-contenteditable-div. The same methods used there should probably work for you. You will most likely need to run this in the componentDidMount() method. Hope that helps. Here is a rough idea of what it would look like:
componentDidMount: function () {
var el = document.getElementById("a3");
var range = document.createRange();
var sel = window.getSelection();
range.setStart(el.childNodes[0], 1);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
el.childNodes[0].focus();
},
Edit: Seeing as your structure is quite nested you'll have to play around a bit with which nodes you are actually selecting to get the desired effect. The focus() call is needed to actually show the applied cursor position if the cursor is not already in the editable element.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With