Draft.js: Common Questions and Answers
Tags: react, javascript, draftjs
Published: 2019-10-26 01:57:35

☀️ Welcome back to my series on Draft.js

Before continuing with more code-stuff with this series, now seems like a good time to hit pause and answer a few questions that I have seen come up fairly often on the [Draft.js Slack Group](https://draftjs.herokuapp.com) (Disclaimer: I don’t actually spend a ton of time lurking there, I am not some super contributor who is always chatting. But I am a member and sometimes I read stuff.)

### What is the best way to save the contents of a form to my database after someone submits the form?
You can do this in different ways, and there are pros and cons to each way 🙂 Below I’ve listed 3 popular options with pros and cons. It’s really up to you to decide what makes the most sense for your situation.

💻 **You could convert to HTML and save as HTML**
* There are several libraries out there that will do this for you. The most popular ones are probably
	* [draft-js-export-html](https://github.com/sstur/draft-js-utils/tree/master/packages/draft-js-export-html) and
	* [draft-js-import-html](https://github.com/sstur/draft-js-utils/tree/master/packages/draft-js-import-html)
* 👍 **Pro:** Easy to later render elsewhere outside of the editor
* 👍 **Pro:** Not locked in to any proprietary Draft.js conventions if you later switch to a new editor.
* 👎 **Con:** Have to convert back and forth from HTML to a Draft.js format if you want to edit it later. Not a big deal but there does run the risk of conversion bugs where things don’t convert perfectly.

**🖋 You could save as a raw draftjs object**
* Draft.js provides a couple of [utility functions](https://draftjs.org/docs/api-reference-data-conversion): `convertToRaw` and `convertFromRaw` which take your Editor’s `ContentState` and makes it an object that you can easily save on your database.  You can also easily re-convert to a `ContentState` back from the object.
* 👍 **Pro:** No risk of conversion bugs because you’re saving Draft.js’s exact state
* 👎 **Con:** You will need to find some way to render that content outside of the editor, if that’s a functionality you need.
* 👎 **Con:** If you ever decide to switch to a different rich text editor, you need to write something to convert all your existing saved data to a new format supported by the new editor.

**🖍 You could save in another format, like markdown**
* Similar to HTML, libraries already exist for this.
	* [draft-js-export-markdown](https://github.com/sstur/draft-js-utils/blob/master/packages/draft-js-export-markdown) and
	* [draft-js-import-markdown](https://github.com/sstur/draft-js-utils/tree/master/packages/draft-js-import-markdown)
	* [markdown-draft-js](https://github.com/Rosey/markdown-draft-js) (shameless, as I maintain this one)
* 👍 **Pro:** Easy to later render elsewhere outside of the editor
* 👍 **Pro:** Not locked in to any proprietary Draft.js conventions if you later switch to a new editor.
* 👍 **Pro:** If you want to let people toggle between markdown and non-markdown mode seamlessly when editing text, this could be a good use case for saving as markdown.
* 👎 **Con:** If you plan on rendering the content in HTML or some other format outside of the editor, you have to take the additional step of converting the markdown.
* 👎 **Con:** Markdown behaves a bit differently from “normal” plain text, in that it strips multiple newlines. This may cause problems - if someone has ten empty lines between paragraphs, markdown by default will strip them so people won’t see EXACTLY what they saved. There are work-arounds but 🤷‍♀️
* 👎 **Con:** Same as HTML: Have to convert back and forth from markdown to a Draft.js format if you want to edit it later.

### What is the best way to render the rich text (eg in a comment feed, if the form is for writing a comment) after someone submits a form?

If you are saving the raw object and need a way to then convert it to HTML for rendering purposes, this library exists: [draftjs-to-html](https://github.com/jpuri/draftjs-to-html)

There’s also a library for rendering in react native here:  [react-native-draftjs-render](https://github.com/globocom/react-native-draftjs-render)

### How do I get the placeholder to work like a normal placeholder in an input?
You can pass in `placeholder=“Your placeholder text here"` to the Editor component just like you can with a regular input or textarea, but as you may have noticed, by default it doesn’t really behave the way you’d probably like it to.

My go-to for this is to use a bit of CSS.

1. Set to `position: absolute` so it doesn’t take up any space
2. Set to `pointer-events: none` so that it doesn’t block you from click-to-focus on the editor
3. Change its colour to something a bit more placeholder-y.

Here that is in CSS:

```css
.public-DraftEditorPlaceholder-inner {
  position: absolute;
  color: #ccc;
  pointer-events: none;
}
```

There's another little problem though with the placeholder: If you insert a blockquote or an ordered list, the placeholder hangs around 😧

My solution to this problem is to toggle a class on the parent element to detect if there's some block-level style in place, and add a `hide-placeholder` class if so.


The CSS -
```css
.hide-placeholder .public-DraftEditorPlaceholder-inner {
  display: none
}
```

The JS -

```javascript
const contentState = this.state.editorState.getCurrentContent();
let showPlaceholder = false;
if (!contentState.hasText()) {
  if (contentState.getBlockMap().first().getType() === 'unstyled') {
    showPlaceholder = true;
  }
}
```

Then further down, when rendering, you can do something to dynamically update the className, either using a tool like [classnames](https://www.npmjs.com/package/classnames) or just hardcoding the logic:

```javascript
<div className={`my-little-app ${!showPlaceholder ? 'hide-placeholder' : ''}`}>

```

### Are there any places where I can find a list of useful tools and extensions for Draft?
There are _tons_ of useful tools that people have written. [nikgraf/awesome-draft-js](https://github.com/nikgraf/awesome-draft-js) is a good resource for finding many of them 🙂