React contenteditable курсор переходит к началу
Я использую модуль react-simple-contenteditable чтобы включить редактирование заполнения пустого листа. Причина, по которой я должен использовать редактируемый элемент содержимого вместо элемента ввода, заключается в том, что я хочу, чтобы текст проблемы был обернут. Например, если проблема имеет один пробел, она делит текст на три раздела: часть перед пробелом, пустая и часть после. Если бы я представлял внешние два как отдельные!--3-->s (или поля ввода), тогда текст будет не обернуть как абзац. Вместо этого, я должен иметь один contenteditable div
который содержит поле ввода для пустого и свободного текста с обеих сторон.
текст обтекается, как я хочу, но когда я набираю текст в поле contenteditable, курсор переходит к началу. Я не понимаю, почему, потому что я попробовал пример на сайт модуля github и он работает отлично, и хотя моя реализация немного сложнее, она работает по существу тот же.
вот моя функция визуализации, которая использует <ContentEditable />
:
render() {
const textPieces =
<div className='new-form-text-pieces'>
{
this.props.problem.textPieces.map( (textPiece, idx) => {
if (textPiece.blank) {
return (
<div data-blank={true} className='blank' key={ textPiece.id } style={{display: 'inline'}}>
<input
placeholder="Answer blank"
className='new-form-answer-input'
value={ this.props.problem.textPieces[idx].text }
onChange={ (event) => this.props.handleTextPiecesInput(this.props.problemIdx, idx, event.target.value) }
/>
<button className='modify-blank remove-blank' onClick={ (event) => this.props.removeBlank(this.props.problemIdx, idx) }>-</button>
</div>
);
} else {
let text = this.props.problem.textPieces[idx].text;
const placeholder = idx === 0 ? 'Problem text' : '...continue text';
// text = text === '' ? placeholder : text;
if (text === '') {
text = <span style={{color:'gray'}}>{placeholder}</span>;
} else {
}
return (
this.props.isTextSplit ?
<TextPiece
key={ textPiece.id }
problemIdx={this.props.problemIdx}
textPieceIdx={idx}
dropBlank={this.props.dropBlank}
moveBlank={this.props.moveBlank}
>
<div style={{display: 'inline-block', }}>{text}</div>
</TextPiece>
: text
);
}
})
}
</div>;
return (
this.props.isTextSplit ? textPieces :
<ContentEditable
html={ReactDOMServer.renderToStaticMarkup(textPieces)}
className="my-class"
tagName="div"
onChange={ (event, value) => this.props.handleProblemChange(event, this.props.problemIdx, value) }
contentEditable='plaintext-only'
/>
);
}
здесь onChange
функция:
handleProblemChange(event, problemIdx) {
const problems = cloneDeep(this.state.problems);
event.target.children[0].childNodes.forEach( (textPieceNode, idx) => {
if (textPieceNode.constructor === Text) {
problems[problemIdx].textPieces[idx].text = textPieceNode.wholeText;
} else {
problems[problemIdx].textPieces[idx].text = textPieceNode.childNodes[0].value;
}
});
this.setState({ problems });
}
и вот состояние, на которое он ссылается, просто чтобы прояснить:
this.state = {
problems: [
{
id: shortid.generate(),
textPieces: [
{
text : "Three days was simply not a(n)",
blank : false,
id: shortid.generate(),
},
{
text : "acceptable",
blank : true,
id: shortid.generate(),
},
{
text : "amount of time to complete such a lot of work.",
blank : false,
id: shortid.generate(),
}
]
}
спасибо
1 ответов
короче говоря, нет простого способа сделать это. Я пробовал это сам и потратил дни, пытаясь. В основном вам нужно сохранить положение курсора и переместить его самостоятельно после обновления. Все это может быть достигнуто с окном.getSelection()
https://developer.mozilla.org/en-US/docs/Web/API/Window/getSelection
но это может быть очень сложно в зависимости от того, насколько ваш контент был изменен.
Я закончил использование draftJS вместо. Что является абстракцией над contenteditable div самими facebook.
https://draftjs.org/docs/overview.html#content
немного дольше, чтобы забрать, но вы сможете сделать гораздо больше