Pmon
Pmon

Reputation: 351

Draft JS replace text using handleBeforeInput doesn't change the EditorState

Hi I have a problem in Draft-JS . I want to change the text like when user type ":)" it will change to emoji, But in this example I just want to change some word using "**" for testing. Somehow this.setState new editorstate in handleInput doesnt change the state.

import React, {Component} from 'react';

import {Editor, EditorState,getDefaultKeyBinding,moveFocusToEnd, KeyBindingUtil,getContentStateFragment, SelectionState, Modifier, CompositeDecorator} from 'draft-js';

const storage = {
  "Abm7" : "Abminorseventh"
}
export default class MyEditor extends Component {

  constructor(props) {
    super(props);

    this.state = { editorState: EditorState.createEmpty(), lastOffset:0 };
    this.focus = () => this.refs.editor.focus();
    this.logState = () => console.log(this.state.editorState.toJS());
  }

  onChange(editorState) {
    this.setState({editorState});
  }

  handleBeforeInput(e) {
    if(e === ' ') {

      const { editorState } = this.state;
      const content = editorState.getCurrentContent();
      const selection = editorState.getSelection();
      const end = selection.getEndOffset();

      const block = content.getBlockForKey(selection.getAnchorKey());
      const word = block.getText();
      const result = word.slice(this.state.lastOffset, selection.getEndOffset());
      const newSelection = new SelectionState({
          anchorKey: block.getKey(),
          anchorOffset: 0,
          focusKey: block.getKey(),
          focusOffset: 2
      })
      const contentReplaced = Modifier.replaceText(
                content,
                newSelection,
                "**")
      const editorStateModified = EditorState.push(
         editorState,
         contentReplaced,
         'replace-text'
      );

      this.setState({lastOffset: selection.getEndOffset(), editorState:editorStateModified})
      return true;
    }else {
      return false;
    }
  }

  prompt(e) {
    e.preventDefault();
    const {editorState} = this.state;
    const content = editorState.getCurrentContent();
    const selection = editorState.getSelection();
    const block = editorState.getCurrentContent().getBlockForKey(selection.getAnchorKey());

    let text = block.getText().slice(selection.getStartOffset(), selection.getEndOffset());

    const contentReplaced = Modifier.replaceText(
              content,
              selection,
              storage[text])
    const editorStateModified = EditorState.push(
       editorState,
       contentReplaced,
       'replace-text'
    );
    console.log(editorStateModified.getCurrentContent())
    this.setState({editorState:editorStateModified})
  }

  render() {
    const styles = {
      root: {
        fontFamily: '\'Helvetica\', sans-serif',
        padding: 20,
        width: 600,
      },
      editor: {
        border: '1px solid #ccc',
        cursor: 'text',
        minHeight: 80,
        padding: 10,
      },
      button: {
        marginTop: 10,
        textAlign: 'center',
      },
      buttons: {
          marginBottom: 10,
      },
    };
    return (
      <div style={styles.root}>
        <div style={styles.buttons}>
                <button
                  onMouseDown={(e)=>{this.prompt(e)}}
                  style={{marginRight: 10}}>
                  Change word
                </button>
          </div>
        <div style={styles.editor} onClick={this.focus}>
          <Editor
            editorState={this.state.editorState}
            onChange={(e)=>{this.onChange(e)}}
            handleBeforeInput={(e)=>{this.handleBeforeInput(e)}}
            placeholder="Enter some text..."
            ref="editor"
            />
        </div>
        <input
          onClick={this.logState}
          style={styles.button}
          type="button"
          value="Log State"
          />
      </div>
    );
  }

}

Upvotes: 2

Views: 3472

Answers (1)

Sergey Kopyrin
Sergey Kopyrin

Reputation: 81

The function handleBeforeInput should return "handled", if you want for you changes to be applied. And it should be returned to Editor component, so you need to pass the function to the Editor component as it is, like this:

<Editor
  ...
  handleBeforeInput={this.handleBeforeInput}
  ...
/>

Reference: https://draftjs.org/docs/api-reference-editor#handlebeforeinput

Upvotes: 1

Related Questions