I can't get the html output from draft-js?
Asked Answered
K

6

35

I've been playing around with draft-js by Facebook, but I can't actually figure out how to get the html output of the editor. The console.log in the following example outputs some _map properties, but they don't seem to contain my actual content?

class ContentContainer extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          value: '',
          editorState: EditorState.createEmpty()
        };
        this.onChange = (editorState) => this.setState({editorState});
        this.createContent = this.createContent.bind(this);
      }

      createContent() {
        console.log(this.state.editorState.getCurrentContent());
      }

      render() {
        const {editorState} = this.state;
        const { content } = this.props;
        return (
          <Template>
            <br /><br /><br />
            <ContentList content={content} />
            <div className="content__editor">
              <Editor editorState={editorState} onChange={this.onChange} ref="content"/>
            </div>
            <FormButton text="Create" onClick={this.createContent.bind(this)} />
          </Template>
        );
      }
    }
Korey answered 18/4, 2016 at 8:57 Comment(0)
R
50

There is a handy library I used, draft-js-export-html. Import the library and you should be able to see HTML once you invoke the function, stateToHTML:

console.log(stateToHTML(this.state.editorState.getCurrentContent()));

I'm pretty new to React so hopefully this works for you. I looked under the hood of contentState and there is a fair bit going on there that makes using a library to parse out the entities that much more enticing.

The author, sstur, answers a tangentially-related question where I learned about his libraries.

Ridgepole answered 28/4, 2016 at 3:52 Comment(4)
Consider this one too which is been used in draftjs official examples: github.com/hubspot/draft-convertOdaodab
Had to import it via import { stateToHTML } from "draft-js-export-html"; and then use it as onChange={(e: EditorState) => { onTranslationChange && onTranslationChange( stateToHTML(e.getCurrentContent()), localization.language ); }}Georgianngeorgianna
I don't understand. Why such a fancy editor make it so hard to get the html out? Isn't it the most important requirement of an editor?Alfilaria
this plugin doesn't add inline styles to HTML, is there a way to get the inline styles along with HTML?Wickiup
O
14

Ewan. I am also playing with Draft.js and came across the same problem. Actually, Victor has provided a great solution.

Here are two libraries that I found. The one mentioned by Victor has more stars on GitHub.

https://github.com/sstur/draft-js-export-html

https://github.com/rkpasia/draft-js-exporter

I just want to add that there is a way to print out the content (in JSON format) without using an external library. It is documented under the Data Conversion session.

Here is how I print out user input using the "convertToRaw" function

console.log(convertToRaw(yourEditorContentState.getCurrentContent())); 

Make sure you imported the convertToRaw function from Draft.js by writing:

import { convertFromRaw, convertToRaw } from 'draft-js';

Here is a great blog written by rajaraodv named How Draft.js Represents Rich Text Data. It explained data conversion in detail.

Outvote answered 5/10, 2016 at 19:6 Comment(1)
import {convertFromRaw, convertToRaw} from 'draft-js';Thebes
H
13

There is readonly attribute to generate just HTML:

<Editor editorState={editorState} readOnly/>
Haya answered 29/9, 2016 at 8:59 Comment(2)
After adding this how do I'll get the json, can you please elaborate a little further? for now I'm trying to pull using this.editorRef.current.editor.innerHTML and this is giving without making readonly also. Somewhere I've a feeling this is not right..Khudari
Note that, while this works great if you're already using draft-js in this project, if you're importing draft-js data from a DB, importing draft-js just to convert to HTML is very expensive (12x the unpacked size of draft-js-export-html, for example). And to answer @Kaushik's question, you're not trying to parse JSON; you need to pass in a valid draft-js EditorState object to the editorState field. Check out the draft-js docs if you're not sure how to get that state - this link may help: draftjs.org/docs/api-reference-data-conversionCheslie
E
3

If not willing to add another library to your code, @farincz's approach can work well.

<Editor editorState={this.state.editorState} readOnly/>

The editor state can be directly stored in your storage layer and when you are rendering it to the DOM it is easily available and can help in editing.

By clicking on the text you can make it editable, or bind that click with an edit button. You cannot directly bind click to 'Editor' component, but you can have it on the wrapper containing the 'Editor'.

<div className="editor" onClick={this.editContent.bind(this)}>
  <Editor
    editorState={this.state.editorState}
    onChange={this.onChange}
    handleKeyCommand={this.handleKeyCommand}
    readOnly={this.state.edit}
  />
</div>

Just add 'edit' to your state as true, making sure that readOnly is true (you can make the name 'edit' of the state more obvious, if it is confusing).

this.state = {
 editorState: EditorState.createEmpty(), 
 edit: true
};

Finally change the value of 'edit' to false on click

editContent() {
  this.setState({
    edit: false
  })
}
Ewart answered 4/3, 2017 at 3:27 Comment(0)
A
2

To expand on the libraries shared above, here's another good one : draftjs-to-html

It converts raw editor state (JSON object) into plain HTML.

import draftToHtml from 'draftjs-to-html';
import {convertToRaw} from "draft-js";

const rawContentState = convertToRaw(editorState.getCurrentContent());
const markup = draftToHtml(rawContentState);
Alvinaalvine answered 5/11, 2021 at 13:45 Comment(0)
F
1

The most suitable package to convert to HTML and from HTML is draft-convert

However, you should be aware to use the Advanced usage to be able to convert links and to customize the convert process:

const htmlResult = convertToHTML({
  entityToHTML: (entity, originalText) => {
    if (entity.type === 'LINK') {
      return <a href={entity.data.url}>{originalText}</a>;
    }
    return originalText;
  }
})(editorState.getCurrentContent());


const contentState = convertFromHTML({
    htmlToEntity: (nodeName, node, createEntity): any | void => {
        if (nodeName === 'a') {
            return createEntity(
                'LINK',
                'MUTABLE',
                {url: node.href}
            )
        }
    }
})(htmlInput);
Faitour answered 11/6, 2022 at 18:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.