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