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

немного дольше, чтобы забрать, но вы сможете сделать гораздо больше