DEV Community

Rose
Rose

Posted on

Draft.js: Common Questions and Answers

☀️ 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 (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
  • 👍 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: 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.
  • 👍 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

There’s also a library for rendering in react native here: 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:

.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 -

.hide-placeholder .public-DraftEditorPlaceholder-inner {
  display: none
}

The JS -

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 or just hardcoding the logic:

<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 is a good resource for finding many of them 🙂

Top comments (1)

Collapse
 
olisa_isama_b3849eb38b010 profile image
Olisa Isama

Hi Im having a problem with my decorator instance. Anytime the decorator takes place based on some regex like mention, if a press the spacebar to create another text writing a single char, if i want to erase that char by pressing backspace the cursor moves to the front of the text without erasing the text. But if i type a second character after and perform the backspace to erase the chars after the decorator block it erases