0

I used draft-js-export-html npm and save html to my database as mentioned below.

I followed this link and use npm draft-js-import to import html to editor content with draftjs. I can initialize content with html if my html doesn't contains any images but I am unable to import html if it contains <img> tag.

import React, { Component } from 'react';
import Relay from 'react-relay';
import {Editor, EditorState, RichUtils,DefaultDraftBlockRenderMap,convertToRaw,convertFromRaw} from 'draft-js';
import CreatePostMutation from "../mutations/CreatePostMutation";
import { disconnectAccount, connectAccount, postUpload } from '../serverRequests';
import {stateToHTML} from 'draft-js-export-html';
//text editor's code start
// Custom overrides for "code" style.
const styleMap = {
  CODE: {
    backgroundColor: 'rgba(0, 0, 0, 0.05)',
    fontFamily: '"Inconsolata", "Menlo", "Consolas", monospace',
    fontSize: 16,
    padding: 2,
  },
};

function getBlockStyle(block) {
  switch (block.getType()) {
    case 'blockquote': return 'RichEditor-blockquote';
    default: return null;
  }
}

class StyleButton extends React.Component {
  constructor() {
    super();
    this.onToggle = (e) => {
      e.preventDefault();
      this.props.onToggle(this.props.style);
    };
  }

  render() {
    let className = 'RichEditor-styleButton';
    if (this.props.active) {
      className += ' RichEditor-activeButton';
    }

    return (
      <span className={className} onMouseDown={this.onToggle}>
        {this.props.label}
      </span>
    );
  }
}

const BLOCK_TYPES = [
  {label: 'H1', style: 'header-one'},
  {label: 'H2', style: 'header-two'},
  {label: 'H3', style: 'header-three'},
  {label: 'H4', style: 'header-four'},
  {label: 'H5', style: 'header-five'},
  {label: 'H6', style: 'header-six'},
  {label: 'Blockquote', style: 'blockquote'},
  {label: 'UL', style: 'unordered-list-item'},
  {label: 'OL', style: 'ordered-list-item'},
  {label: 'Code Block', style: 'code-block'},
];

const BlockStyleControls = (props) => {
  const {editorState} = props;
  const selection = editorState.getSelection();
  const blockType = editorState
    .getCurrentContent()
    .getBlockForKey(selection.getStartKey())
    .getType();

  return (
    <div className="RichEditor-controls">
      {BLOCK_TYPES.map((type) =>
        <StyleButton
          key={type.label}
          active={type.style === blockType}
          label={type.label}
          onToggle={props.onToggle}
          style={type.style}
        />
      )}
    </div>
  );
};

var INLINE_STYLES = [
  {label: 'Bold', style: 'BOLD'},
  {label: 'Italic', style: 'ITALIC'},
  {label: 'Underline', style: 'UNDERLINE'},
  {label: 'Monospace', style: 'CODE'},
];

const InlineStyleControls = (props) => {
  var currentStyle = props.editorState.getCurrentInlineStyle();
  return (
    <div className="RichEditor-controls">
      {INLINE_STYLES.map(type =>
        <StyleButton
          key={type.label}
          active={currentStyle.has(type.style)}
          label={type.label}
          onToggle={props.onToggle}
          style={type.style}
        />
      )}
    </div>
  );
};
//text editor's code ends

class BlogForm extends Component {
  constructor(props) {
    super(props);

    let contentState = stateFromHTML(props.post.content);
     this.state = {
       editorState: EditorState.createWithContent(contentState),
     };
    this.focus = () => this.refs.editor.focus();
    this.onChange = (editorState) => this.setState({editorState});
    console.log(editorState)
    this.handleKeyCommand = (command) => this._handleKeyCommand(command);
    this.toggleBlockType = (type) => this._toggleBlockType(type);
    this.toggleInlineStyle = (style) => this._toggleInlineStyle(style);
  }

  _handleKeyCommand(command) {
    const {editorState} = this.state;
    const newState = RichUtils.handleKeyCommand(editorState, command);
    if (newState) {
      this.onChange(newState);
      return true;
    }
    return false;
  }

  _toggleBlockType(blockType) {
    this.onChange(
      RichUtils.toggleBlockType(
        this.state.editorState,
        blockType
      )
    );
  }

  _toggleInlineStyle(inlineStyle) {
    this.onChange(
      RichUtils.toggleInlineStyle(
        this.state.editorState,
        inlineStyle
      )
    );
  }
  handleSubmit = (e) => {
    let html = stateToHTML(this.state.editorState.getCurrentContent());
    e.preventDefault();
    console.dir(this.state.editorState)
    Relay.Store.update(
      new CreatePostMutation({
        title: this.refs.newTitle.value,
        content: html,
        userid: this.props.user.userid
      }),
    );
    this.refs.newTitle.value = "";
  }
  render() {
    const {editorState} = this.state;
    console.log(editorState)
    // If the user changes block type before entering any text, we can
    // either style the placeholder or hide it. Let's just hide it now.
    let className = 'RichEditor-editor';
    var contentState = editorState.getCurrentContent();
    if (!contentState.hasText()) {
      if (contentState.getBlockMap().first().getType() !== 'unstyled') {
        className += ' RichEditor-hidePlaceholder';
      }
    }
    return (
      <div className="col-md-8 col-sm-8 col-xs-12">
        <form onSubmit={this.handleSubmit} className="postForm">
          <div className="form-group">
            <input className="form-control" type="text" required placeholder="Title" ref="newTitle" />
          </div>
          <div className="form-group">

            <div className="RichEditor-root">
              <BlockStyleControls
                editorState={editorState}
                onToggle={this.toggleBlockType}
                />
              <InlineStyleControls
                editorState={editorState}
                onToggle={this.toggleInlineStyle}
                />
              <div className={className} onClick={this.focus}>
                <Editor
                  blockStyleFn={getBlockStyle}
                  customStyleMap={styleMap}
                  editorState={editorState}
                  handleKeyCommand={this.handleKeyCommand}
                  onChange={this.onChange}
                  placeholder="Enter Content..."
                  ref="editor"
                  spellCheck={true}
                  />
              </div>
            </div>
          </div>
          <div className="form-group"> 
            <input type="file" name="avatar" ref="avatar" onChange={(e)=>this.handleImageSelect(e)} className="form-control padding upload-input" placeholder="Change image" />
          </div>
          <button className="btn btn-primary allbtn-btn" type="submit">Submit</button>
        </form>
      </div>
    )
  }
}
export default BlogForm

As it is generating error

Uncaught Invariant Violation: Component(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.

I also tried with this link and also used convertFromHtml but stll unable to initialize editor with <img> tag

Thanks in Advance

Community
  • 1
  • 1
akshay
  • 1,151
  • 1
  • 19
  • 31
  • Please let me know If I need to mention any other source code.As whole code can be referred from my [blog](http://draftjs.blogspot.in/) link – akshay Aug 15 '16 at 04:47

2 Answers2

2

You do not need to use external plugins to convert draftjs content to HTML as Draft.js provides a function called convertToRaw(for exporting data) and convertFromRaw(for importing data).

ajooba
  • 110
  • 6
  • 5
    Both of these are not providing the HTML of the content. Please share with us If this is possible to do. How can we get the HTML of the editor content using these convertToRaw and convertFromRaw. According to the my knowledge we have to use a external plugin to render the content into a HTML version. – Eranga Kapukotuwa Nov 28 '16 at 10:34
  • There is a `convertFromHTML` function in Draft.js: https://draftjs.org/docs/api-reference-data-conversion.html#convertfromhtml – Neurotransmitter Apr 03 '19 at 08:51
1

You need a blockRenderMap and blockRenderFn to support images, as Draft-JS doesn't bundle support for these. Check out draft-js-plugins as there is a (presently, Oct 31st 2016, broken) image plugin, and my image plugin example on Draft-js-base-plugin.