Unelss I'm missing something, I can't seem to get the html output of the editor, or do I need to do that myself somehow? The docs aren't too clear on how to do that.
Here's my React component...
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>
);
}
}
The console.log outputs some _map or something?
Thanks in advance!
@EwanValentine Draft.js doesn't have a toHtml method or anything like that. It has a convertToRaw function though. It will return a structured text result that you can then process however you like. There are repos that have some work done on toHtml processing. The idea is — Draft.js doesn't have any assumptions about the output format so you can really fine tune your output
Ahaa! That makes perfect sense, I was struggling to understand what I myself needed to provide in that scenario.
Okay great, I'll search around to see how others have done that.
Thanks again!
@alexeygolev I hear what you're saying about not making assumptions about the output format, but this seems like a giant lacuna in the library, or at least the documentation. Anyone using Draft.js to do rich text editing in an input field is likely going to have to display that edited text somewhere, and it's likely (90%? 95%? 99%?) that the ultimate output is going to be HTML.
I think if Draft.js isn't going to support this as part of the core functionality, the least that could be done would be addressing this in the docs and recommending and/or blessing some third party repos as a way to go about solving this. Hunting around in the repo's issues for even a hint about how to handle this just sucks.
PS: @EwanValentine - did you end up choosing a third-party repo? Anything you'd recommend?
@jtulk I agree with you here. I find it frustrating that we have this great editor, but no way to actually use the content it provides.
Leaving this here: https://github.com/sstur/draft-js-export-html
I'm currently using this and have it working. ( cc: @rscott78 )
@EwanValentine @jtulk @rscott78
Facebook developers like @hellendag decided to open source Draft.js, a React component built for use with the React library specifically. With that in mind, it makes sense that the Draft.js library doesn't have a convertToHTML function by default. The common case of using Draft.js with React means that the React library (not Draft.js) handles rendering all React components, including the Draft.js Editor, to HTML.
In fact, looking at the history of Draft.js, the library didn't even ship with the now included convertFromHTML function; this functionality was added 18 days later. This fact seems to imply that contributors to Draft.js realized some developers consuming the Draft.js library might want to hydrate the state of the Editor with HTML. Furthermore, other developers (like those on this thread and myself) would benefit from a function converting Editor state to HTML, in order to use this exported HTML outside of the React view rendering model, e.g. a rich-text email editor.
The wonderful thing about Github is that it provides a platform for developers to share the code they write with others. When @sstur discovered the need to convert the Editor state to HTML, he developed and published a module providing that functionality. The power behind Github's platform lies in its ability to empower software developers to share solutions to problems that other developers might be encountering.
While I would love for Draft.js to provide the functionality of exporting convertToHTML by default, it is important to clarify that this is not the common use case of the Draft.js library. Demanding that a library provide new functionality not a part of its intended use case seems unfair. Of course there is plenty of room for improvement in the open source community, especially communication between contributors to projects, developers using libraries, new contributors being onboarded, developers new to using a library, etc. However, let's remember to be empathetic in our speech to others as we try to reach understanding together.
@baldwmic If you read the thread, I think you'll see that we're all fine with Draft.js not supporting HTML export. And we're all familiar with how Github works and the benefits/frustrations of working with open-source software. The specific request here is to make it a little easier to find out _sooner_ that HTML exporting isn't supported, and if possible, be directed to libraries like draft-js-export-html without having to spend a couple of hours gleaning the docs and Google before finding a buried issue thread (that's how you got here too, right?).
It may be that I'm wrong, but my gut is that actually displaying the rich content collected via Draft.js in HTML (or other) is likely a MAJOR use case of the library, and as such, possibly deserves at least a nod in its general direction somewhere. My take is that this issue is like opening an online bank, not mentioning partner ATMs, and then telling people interested in accessing their money that a physical ATM network isn't the mission of an online-only bank. We'd all agree that while technically correct, it's hardly helpful.
@jtulk after reading your thoughts and exploring Draft.js further, I realize you are right on several fronts and I was wrong! Here's a way to pull out the HTML Draft.js renders by default...
this.refs.editor.refs.editor.innerHTML when Editor component has ref of editor will retrieve HTML Draft.js renders by default.
While Draft.js doesn't export a helper function to convert a serialized raw editor object to HTML, it does convert the editor contents to HTML behind the scenes. Yes, Draft.js uses React as a functional view library, but the React Editor component must provide the HTML markup content for React to render something to the DOM. In fact, using refs we can reach in and get the innerHTML of the editor.
Let's verify this for ourselves. For instance, take the rich Draft.js example , and modify the onChange function from this:
this.onChange = (editorState) => this.setState({editorState});
to this:
this.onChange = (editorState) => {
this.setState({editorState});
console.log(this.refs.editor.refs.editor.innerHTML);
}
If you open the modified HTML page in the Chrome browser and open up the Developer Tools window, you will see the HTML Draft.js provides to React when you use the editor. You can verify that the HTML works on its own by copying it into a JSFiddle like I've done here: Draft.js Rich Example HTML - JSFiddle
We can even see how Draft.js takes it's editor's contents and renders HTML since the code is open sourced!
data-text=true class is present.It would be great if we could add @baldwmic solution to the examples directory and name it convertToHTML as counterpart to the already existing convertFromHTML example.
I have a suggestion I found to a working presententional of Exactly what I needed, there is a prop to the Editor, of readOnly.
Now all I need is to to save editor state and present it with read only (quick and good enough for my case)
I didn't want to use another library to access the HTML rendered by the draft input as it is right there already in the DOM and it would seem that all you have to do is go get it. This is what I came up with:
// In the render...
// You must give React a string to use as a Ref to the DOM later.
<Editor editorState={editorState} onChange={this.onChange} ref="draftRef"/>
// In the code where you want the HTML, for example in some click handler.
// Use the same string you gave in ref to the Editor in render
var draft-ref = this.refs.draftRef;
// Get the root DOM element for the Editor
var draft-dom = ReactDOM.findDOMNode( draft-ref );
// Get the rendered content from the DOM
var html = draft-dom.querySelector("div[data-block] div[data-offset-key]").innerHTML;
// Now just apply your html to wherever you want it...
The following approach is not recommended by the authors see this comment instead
Original:
In case anyone happens on this issue recently, the HTML is actually stored in this.refs.editor.editor.innerHTML of the component rendering the <Editor/>. Also if you're doing this in a recent version of react you should instead initialize a ref using this.editorRef = React.createRef(), then use this.editorRef as the Editors ref prop, and access it via this.editorRef.current.editor.innerHTML
While retrieving and storing the HTML like described above might seem to work, it’s really not meant to be used like that and you’re going to run into issues in the long run. The HTML that Draft.js renders in the editor isn’t meant for storage. The problems will come when you save the HTML and then initialise a new editor with it (say when editing existing content) – some of the content might get lost in the conversion.
The reason for this is that convertFromHTML only handles very basic formatting from e.g. a rich text copy-paste. It's not meant to retain all content like the convertFromRaw and convertToRaw functions do.
You can experience such issues with preserving content as HTML on https://draftjs.org/ by copy-pasting between editors in two different tabs, for example:

That specific issue is #523, but I would expect many more problems with the approach (e.g. line breaks will most likely be lost too). For example, any custom rich text (say an "Embed" block, or an "action" list) will be lost.
If you want to convert Draft.js content to HTML reliably, have a look at one of the many helper libraries that do this: https://github.com/nikgraf/awesome-draft-js#common-utilities
Thanks for the insight @thibaudcolas I will take a look!
Above solutions didn't work in my case where I get the 'this' reference as Draft JS editor.
So I modified the code little, like below.
let _self = this;
this.onChange = editorState => {
this.setState({ editorState });
console.log(_self.refs.editor.editor.innerHTML);
};
Thank you.
Thank you for your solution @BalasubramaniM ! It works but beware though because your solution is not always in sync with the current editor's value (this is an issue that I am experiencing using your solution)
I think @baldwmic's solution on how to grab the HTML should be noted on this documentation page: https://draftjs.org/docs/api-reference-data-conversion/
For people who want the possibility of editing the content again in the future you should also use convertToRaw(), store it as JSON, and later use convertFromRaw() to edit the content.
Thanks to everyone above for helping me solve this! For anyone looking for a modern (hook-based) version of @ghost's approach, here's a basic example. It retains the normal onChange (controlled input) behavior, but also saves the editor's HTML to a provided callback onBlur:
({ saveHTML }) => {
// Make a regular React ref
const editorRef = useRef();
// Make your EditorState state as normal with useState
const [editorState, setEditorState] = useState(() => EditorState.createEmpty());
// Use the ref to access the HTML, and pass it to a "save" callback
const onBlur = () => saveHTML(editorRef.current.editor.innerHTML)
// Give your editor state and onChange handler as normal, but also pass the ref
return <Editor editorState={editorState} onBlur={onBlur} onChange={setEditorState} ref={editorRef} />
}
(My kingdom for a toHTML method!)
I’ll repeat my warning from https://github.com/facebook/draft-js/issues/319#issuecomment-395996499 in case it’s not clear enough – the editor’s innerHTML isn’t something you should rely on for anything serious, as it retrieves the HTML the editor uses for editing purposes, which isn’t meant for storage, and isn’t suitable to render on websites either.
You should instead use one of the many import/export utilities people have built as separate packages, for example draft-convert, which implements those convertToHTML and convertFromHTML functions in a way that’s sensible. It would be great for Draft.js to have something like this built-in, but it doesn’t currently. The maintainers of Draft.js should document this somewhere since it’s such a frequently requested feature.
Here is another example of a very basic issue with grabbing the innerHTML – nested lists:

If using .innerHTML, you would get the following markup. Note how it’s not nested – Draft.js only uses special "depth" classes to mimick nesting:
<ul>
<li class="public-DraftStyleDefault-depth0">
<div data-offset-key="eptio-0-0" class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"><span data-offset-key="eptio-0-0"><span data-text="true">test</span></span></div>
</li>
<li class="public-DraftStyleDefault-depth1">
<div data-offset-key="cf9nf-0-0" class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"><span data-offset-key="cf9nf-0-0"><span data-text="true">test</span></span></div>
</li>
<li class="public-DraftStyleDefault-depth0">
<div data-offset-key="6dmo4-0-0" class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"><span data-offset-key="6dmo4-0-0"><span data-text="true">test</span></span></div>
</li>
</ul>
What you would actually want is something like this, really using a nested ul:
<ul>
<li>
test
<ul>
<li>test</li>
</ul>
</li>
<li>test</li>
</ul>
I also updated my comment to reflect that the approach is not recommended
I wonder if someone looked at converting RawDraftContentState https://draftjs.org/docs/api-reference-data-conversion/
back to jsx, so that we can use draftjs to build a WYSWG editor for react components. Maybe someone can point me in the right direction: How can I go from javascript objects back to JSX? what I need is basically a JSX decompiler.
Cheers! :smile:
EDIT: okay i found some interesting things: https://github.com/algolia/react-element-to-jsx-string
https://github.com/repetere/jsonx
Most helpful comment
@alexeygolev I hear what you're saying about not making assumptions about the output format, but this seems like a giant lacuna in the library, or at least the documentation. Anyone using Draft.js to do rich text editing in an input field is likely going to have to display that edited text somewhere, and it's likely (90%? 95%? 99%?) that the ultimate output is going to be HTML.
I think if Draft.js isn't going to support this as part of the core functionality, the least that could be done would be addressing this in the docs and recommending and/or blessing some third party repos as a way to go about solving this. Hunting around in the repo's issues for even a hint about how to handle this just sucks.
PS: @EwanValentine - did you end up choosing a third-party repo? Anything you'd recommend?