by Andrey Semin
How to paste images directly into an article in Draft.js
For some of you this may be a surprise, but Draft.js doesn’t support images out of the box. To be able to display images in the Editor, you need to install and configure
draft-js-image-plugin (we won’t cover this topic here as its docs are pretty comprehensive). This also means there is no support for such a common feature like pasting images (or any other file) into the Editor. The goal of this post is to show how you can add basic support for pasting files (we will focus on images).
Let’s start by reading the Draft.js docs. It turns out there is a prop called
handlePastedFiles in the Editor. It receives an array of files and is supposed to provide you the option to manipulate with files on a paste action. However, things don’t work exactly this way.
There is an issue: when you try to paste multiple files into the Editor you will receive an array containing only one of them. This is a known problem and there was an issue opened in the Draft.js repo on 11 of December 2018. Which means it’s pretty young but still annoying.
Now we need to define which file types we’re going to handle. For images, those are
Now when we know we are going to work only with images, it is time to actually read the data from the file. To do this we will implement a function called
readImageAsDataUrl and use the
FileReader API and
readAsDataUrl methods in particular. This combination of steps allows us to read the file and its content in base64 encoding which later can be used as a value of the
src attribute of the
Now when we have our base64 encoded image, all we need to do is to create a Draft.js entity and update the Editor’s state to contain this entity.
We can start by using the
create method of the
Entity module that is a part of Draft.js. (Keep in mind, though, that the documentation states
Entity.create is deprecated and developers should use
contentState.createEntity. The last one was not working at the time this post was written. So we’ll proceed with the usage of
Entity but will keep track of this change).
We need to provide 3 arguments here:
- the first is the type of entity we’re about to create (
imagein our case)
- the second is the mutability of the entity (
IMMUTABLEmeans we can’t edit the content of the text containing this entity. If we try to remove something from it, the whole text range would be removed)
- and the third is an optional object containing any data you want to store with an entity (in our case it is
srcwhich is required by
In return we get a key by which we can address this entity in the Editor state. Now we need to use this key to insert a block into the editor and attach this exact entity to this block. We will use the
insertAtomicBlock function of the
AtomicBlockUtils module from Draft.js. We need to pass the current Editor state, entity key, and a character (that should not be empty string — that’s why we use single space) and we will get a new Editor state!
Now when all is set let’s combine everything together and take a look at our
Voilà! Now we can paste the image into Draft.js editor by simply pressing CTRL+V. You can extend this functionality in any way we want! For example we can allow our users to change the size of the images with some fancy UI.
If you’ve read this post all the way through, you may also want to check out my previous post about Draft.js enchantment. You may want to apply it to your project as well.