Search code examples
javascriptreactjsdraftjs

How to insert / upload image (update entity and blocks) in Draft.js?


I am trying to insert image to Draft.js editor.

Based on my understanding, I need update entity by mergeData and blocks by mergeBlockData. (I am not sure)

Now I am trying to use mergeBlockData to insert a block.

mergeBlockData(
  contentState: ContentState,
  selectionState: SelectionState,
  blockData: Map<any, any>
): ContentState

Please read comment in the code.

import { Map } from 'immutable';

const selection = this.state.editorState.getSelection();
const contentState = this.state.editorState.getCurrentContent();

console.log(convertToRaw(contentState));  // for example, I have 3 blocks

const blockData = Map({ ov72: {  // here how to generate a random valid key?
  "key": "ov72",
  "text": " ",
  "type": "atomic",
  "depth": 0,
  "inlineStyleRanges": [],
  "entityRanges": [{
    "offset": 0,
    "length": 1,
    "key": 1
  }],
  "data": {}
}});
const newContentState = Modifier.mergeBlockData(contentState, selection, blockData);

console.log(convertToRaw(newContentState));  // here is wrong, still 3 blocks. Also original blocks have no change

const newEditorState = EditorState.push(this.state.editorState, newContentState);

Solution

  • Took a while to figure out how to insert image.

      insertImage = (editorState, base64) => {
        const contentState = editorState.getCurrentContent();
        const contentStateWithEntity = contentState.createEntity(
          'image',
          'IMMUTABLE',
          { src: base64 },
        );
        const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
        const newEditorState = EditorState.set(
          editorState,
          { currentContent: contentStateWithEntity },
        );
        return AtomicBlockUtils.insertAtomicBlock(newEditorState, entityKey, ' ');
      };
    

    Then you can use

    const base64 = 'aValidBase64String';
    const newEditorState = this.insertImage(this.state.editorState, base64);
    this.setState({ editorState: newEditorState });
    

    For render image, you can use Draft.js image plugin.

    Live demo: codesandbox

    The demo inserts a Twitter logo image.


    If you want to insert a image from local file, you can try to use FileReader API to get that base64.

    For how to get base64, it is simple, check

    Live demo: jsbin

    Now go ahead to put them together, you can upload image from local file!