Draft.js: how to remove formatting of the text

Written by semin_andrey | Published 2018/10/20
Tech Story Tags: javascript | react | draftjs | web-development | front-end-development

TLDRvia the TL;DR App

One of the features that we at Propeller miss in Draft.js out-of-the-box is the possibility to clear the stylings of selected text, leaving plain text inside the editor. We believe this behaviour is commonly used and our users may expect this feature to be on it’s place. As always in order to add this feature you would need to spend significant amount of time digging into Draft.js documentation in order to find required information.

This post describes what steps you should take in order to add this behaviour into your project.

TL;DR

As always, there is a npm package available for you not to implement everything manually.

All editing in Draft.js may be divided into 3 groups:

  • Inline styles
  • Custom entities(for example images, links etc.)
  • Block types

In order to clean the text up we need to take care of all of these groups.

Inline Styles

This one is pretty simple. First, we need to define a list of styles which we support in the project (in our case — Bold, Italic and Underline texts). Next, we need to call a method called removeInlineStyles of Modifier module that comes as a part of Draft.js package. Obviously enough, this method allows us to remove specified inline style from the selected range. So we need to call it for each item of our styles array.

To simplify the code, we would use reduce method here. If you are not familiar with it — you can read about it here.

Note that we use 2 different editorStates here — the argument we pass in the function which represents current state of the editor and EditorState which should be imported from Draft.js itself along with Modifier module.

push method is used to create a new EditorState object with applied contentWithoutStyles as a content of the editor.

Note the third parameter we pass to push method(a string change-inline-style ). This parameter is called changeType and Draft.js uses it to specify a correct undo/redo behaviour. This particular one means that inline style has been applied or removed for one or more characters.

Entities

This one is even easier. We don’t need to build any additional array of styles or use any iteration functions. Instead we need to call applyEntity method of the exact same Modifier module. This method allows us to apply an entity to the selected range. In order to remove all entities we need to pass null as a third argument to this function.

And again you may notice that we use apply-entity as a change type in EditorState.push() call. This one means an entity has been applied or removed to one or more characters.

Block Types

The complex one. In order to remove different block types(headers, list items, code blocks etc.) from the selection range and preserve the text we need to change the type of each block to be unstyled . You can read more about what a block is and why it has different types here. This post is not 100% actual nowadays but it gives right mindset to better understand how Draft.js works.

And the best way to change the type of block is to go through all of them and to call a change function for each singe one of them.

First, we need to get all the blocks from the selection range. Here we may want to use getSelectedBlocksMap method from [draftjs-utils](https://github.com/jpuri/draftjs-utils) package.

Next we need to detect whether we want to perform any action on the block. In our case we need to check the block type and we do so by calling getType method of the block. So if the block has any type (blockType !== ‘unstyled’) — the block should be updated.

Once we find a block to update we need to change it’s type. Here we need to update the selection range to select whole block(you can use text length here to set the end index of the selection range).

Now we need to call setBlockType method of Modifier module to update the type of the block and get new contentState and then we need to push it to the EditorState. This functions expects to get a blockType parameter which in our case should be unstyled as we want to wipe all of the edits. The change type for this operation is change-block-type. I guess by now you get what it means :)

Let’s combine it all together and use reduce method to simplify the code so we run EditorState.push() only once like we’ve done in Inline Styles section.

Combining everything together

All set now! Let’s get all these functions to work! I would recommend to use flow function of lodash package or any of the alternatives here because it would drastically increase the readability of the code. Let’s try it out:

And here is the result:

We select all the text, hit ‘Clear’ button and all editing is removed!

If you’ve read this post till this moment you may also want to check my previous post about Draft.js enchantment and apply it to your project as well.


Published by HackerNoon on 2018/10/20