Korzystam z modułu react-simple-contenteditable, aby umożliwić edycję wypełnienia pustego arkusza roboczego. Powodem, dla którego muszę użyć edytowalnego elementu zawartości zamiast elementu wejściowego, jest to, że chcę zawinąć tekst problemu. Na przykład, jeśli problem ma jedno puste miejsce, dzieli tekst na trzy sekcje część przed pustym, puste i część po. Gdybym miał reprezentować zewnętrzne dwa jako oddzielne div
s (lub pola wejściowe), to tekst nie byłby zawijany jak akapit. Zamiast tego, muszę mieć jeden contenteditable div
, który zawiera pole wejściowe dla pustego i dowolnego tekstu po obu stronach.Reaktywny kursor z możliwością reagowania przeskakuje do początku
Tekst jest zawijany tak, jak chcę, ale gdy wpiszesz tekst w polu contenteditable, kursor przeskoczy na początek. Nie rozumiem dlaczego, ponieważ próbowałem przykładu na module's github site i działa idealnie, i chociaż moja implementacja jest nieco bardziej skomplikowana, działa zasadniczo tak samo.
Oto moja renderowanie funkcja, która wykorzystuje <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'
/>
);
}
Oto onChange
funkcja:
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 });
}
A oto stan odnosi się tylko do rzeczy oczywiste:
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(),
}
]
}
Wielkie dzięki
Dzięki za odpowiedź! Ponownie przyjrzę się DraftJS, wygląda to dość skomplikowanie. Czy można go zaimplementować tylko dla prostych pól, takich jak to, co robię, czy jest to po prostu dla edycji tekstu sformatowanego, jak to jest reklamowane? –
Może zrobić jedno i drugie. Chociaż nie jest to proste, założę się, że jest prostsze niż zarządzanie stanem kursora. – klugjo
Wracając do tego teraz ... Przeszukałem dokumentację DraftJS i nie mogę znaleźć odpowiedzi na inne pytanie, więc pomyślałem, że być może wiesz: czy mogę utworzyć elementy html zawartości wewnętrznej? Oprócz tekstu, który można edytować, potrzebuję tekstu z ramką wokół niego. –