Word matching
Word matching

Reputation: 11

How to Decorate a text with Modifier in Draft.js

I'm trying to decorate some text, but instead of making the process managed by a regex strategy, it should be the results of an ajax call to specify which peace of text to decorate. Is it possible to use any method from Modifier library? My idea is to call something inside the onChange method and modify the editorstate. Any idea would be appreciated.

Upvotes: 1

Views: 2014

Answers (1)

Vasanthakumar V
Vasanthakumar V

Reputation: 88

My solution uses a custom decorator and a dynamic regex, this combination might help achieve the effect you are hoping for.

Code structure follows this example to decorate tweets in draftjs.

enter image description here

You can replace the string array (var arr = ["one", "two", "three"]) in the code with an ajax call.

import React, { Component } from 'react';
import { Editor, EditorState, CompositeDecorator } from 'draft-js';

const styles = {
  handle: {
    color: 'black',
    backgroundColor: '#FF7F7F',
    direction: 'ltr',
    unicodeBidi: 'bidi-override',
  },
};

// arr can be accessed from an ajax call
var arr = ["one", "two", "three"]
const HANDLE_REGEX = new RegExp("(?:[\\s]|^)(" + arr.join("|") + ")(?=[\\s]|$)", 'gi')

function handleStrategy(contentBlock, callback, contentState) {
  findWithRegex(HANDLE_REGEX, contentBlock, callback);
}

function findWithRegex(regex, contentBlock, callback) {
  const text = contentBlock.getText();
  let matchArr, start;
  while ((matchArr = regex.exec(text)) !== null) {
    start = matchArr.index;
    callback(start, start + matchArr[0].length);
  }
}
const HandleSpan = (props) => {
  return (
    <span
      style={styles.handle}      
      data-offset-key={props.offsetKey}
    >
      {props.children}
    </span>
  );
};


class App extends Component {
  constructor(props) {
    super(props);
    const compositeDecorator = new CompositeDecorator([
      {
        strategy: handleStrategy,
        component: HandleSpan,
      }
    ]);
    this.state = {
      editorState: EditorState.createEmpty(compositeDecorator),
    };
    this.onChange = (editorState) => this.setState({editorState});
  }
  render() {
    return (
      <div className="container-root">
      <Editor
        editorState={this.state.editorState}
        onChange={this.onChange}
        placeholder="Write..."
        ref="editor"
        spellCheck={true}
      />
      </div>
    );
  }
}

export default App;

Upvotes: 3

Related Questions