Я бы хотел, чтобы мой текстовый редактор отображал, сколько раз блок контента был выбран и выполнен с помощью ключевой команды. Я делаю это, применяя сущность к выбранному блоку со свойством evaluatedTimes
. Данные изменяются правильно, но компонент сущности не рендерится повторно, пока я не вставлю новые символы в блок текста.
Стратегия декорирования сущности не вызывается, поэтому единственный выход найдено - обновить состояние редактора новым экземпляром декоратора. Таким образом, компоненты сущности повторно визуализируются, но решение заполняется немного хакерскими.
зависимости:
"draft-js": "^0.11.3",
"draft-js-plugins-editor": "^3.0.0",
"draftjs-utils": "^0.10.2"
код:
// plugin.js
import { EditorState } from "draft-js";
import { getSelectionText, getSelectionEntity } from "draftjs-utils";
import { EvaluatedSpan } from "./components";
import { findEvaluatedEntities, createEvaluatedEntity } from "./entities";
export function createCodeEvaluationPlugin({ onEvaluate = () => {} }) {
return {
decorators: [
{
strategy: findEvaluatedEntities,
component: EvaluatedSpan
}
],
keyBindingFn: e => {
// CMD + ENTER
if (e.metaKey && e.keyCode === 13) {
return "evaluate";
}
},
handleKeyCommand: (command, editorState, _, { setEditorState }) => {
if (command === "evaluate") {
const selectionState = editorState.getSelection();
const contentState = editorState.getCurrentContent();
const entityKey = getSelectionEntity(editorState);
// If selection contains an entity:
if (!entityKey) {
// Create new entity and update editor.
setEditorState(createEvaluatedEntity(editorState, selectionState));
} else {
// Modify entity data.
const entity = contentState.getEntity(entityKey);
const nextContentState = contentState.mergeEntityData(entityKey, {
evaluatedTimes: entity.data.evaluatedTimes + 1
});
// Update editor.
setEditorState(
EditorState.push(editorState, nextContentState, "change-block-data")
);
}
// Pass text to callback handle
const selectionText = getSelectionText(editorState);
onEvaluate(selectionText);
return "handled";
}
return "not-handled";
}
};
}