Draft.js вставляет один contentState в другой

У меня есть редактор Draft.js с некоторым HTML в нем. Как я могу вставить новый фрагмент HTML в текущую позицию выделения, сохраняя стили и отображения сущностей / блоков? Я знаю, как вставить сырой текст с помощью Modifier.insertText:

const contentState = Modifier.insertText(
  editorState.getCurrentContent(),
  editorState.getSelection(),
  insertionText,
  editorState.getCurrentInlineStyle(),
);

но это лишит весь HTML, который не в порядке.

// Original HTML piece
const { contentBlocks, entityMap } = htmlToDraft(originalHTML);
const contentState = ContentState.createFromBlockArray(
  contentBlocks,
  entityMap,
);
const editorState = EditorState.createWithContent(contentState);

// Additional HTML piece, which I want to insert at the selection (cursor) position of
// previous editor state
const { contentBlocks, entityMap } = htmlToDraft(newHTML);
const newContentState = ContentState.createFromBlockArray(
  contentBlocks,
  entityMap,
);

2 ответа

Вам, вероятно, следует использовать Modifier.replaceWithFragment за это:

"Фрагмент" - это часть блочной карты, фактически просто OrderedMap, почти такая же, как полная блочная карта объекта ContentState. Этот метод заменит "целевой" диапазон на фрагмент.

Это будет работать идентично insertText, за исключением того, что вам нужно передать ему карту блоков в качестве параметра. Из вашего примера не совсем понятно, какое возвращаемое значениеhtmlToDraft есть, но вы должны иметь возможность:

  • Использовать contentBlocks прямо из возвращаемого значения
  • Или создайте contentState как в вашем примере, затем используйте его .getBlockMap(), чтобы получить карту блоков для вставки в содержимое редактора.
const newContentState = ContentState.createFromBlockArray(
  contentBlocks,
  entityMap,
);
// Use newContentState.getBlockMap()

Я не мог опубликовать это в разделе комментариев (слишком длинный фрагмент), но, как упоминалось ранее Modifier.replaceWithFragmentэто путь, поэтому я заставил его работать, как в приведенном ниже фрагменте.

*** Убедитесь, что у вас есть вся остальная инфраструктура, например blockRendererFn, blockRenderMap, compositeDecorator, и т. д., чтобы фактически отображать все эти блоки, встроенные стили для ссылок, изображений и т. д.

      import {
    Modifier,
    ContentState,
    convertFromHTML,
} from 'draft-js'

onPaste = (text, html, state) => {
    if (html) {
        const blocks = convertFromHTML(html)
        Modifier.replaceWithFragment(
            this.state.editorState.getCurrentContent(),
            this.state.editorState.getSelection(),
            ContentState.createFromBlockArray(blocks, blocks.entityMap).getBlockMap(),
        )
    }
    return false
}
Другие вопросы по тегам