Build a Rich Text Editor with Editor.js

Build a Rich Text Editor with Editor.js

Block-styled editor with vanilla JavaScript

[Demo of Editor.js](https://cdn.hashnode.com/res/hashnode/image/upload/v1630754283090/vCEshR0sW.html)Demo of Editor.js

Editor.js is a modern, feature-rich block styled editor. The most highlighting feature of Editor.js is that it is a block-styled editor which means it creates separate blocks for different elements like paragraphs, images, lists, etc.

This also enables the Editor.js to render clean, JSON data. Other text editors such as Draft.js produce HTML-markup data which is harder to store compared to the JSON data output of Editor.js. This is what the data output looks like:

{
   "time": 1550476186479,
   "blocks": [
      {
         "type": "header",
         "data": {
            "text": "Editor.js",
            "level": 2
         }
      },
      {
         "type": "paragraph",
         "data": {
            "text": "Hey. Meet the new Editor. On this page you can see it in action — try to edit this text. Source code of the page contains the example of connection and configuration."
         }
      },
      {
         "type": "header",
         "data": {
            "text": "Key features",
            "level": 3
         }
      },
}

Moreover, you can create your own renderer for the data output of Editor.js since the data is in JSON.

It works with vanilla JavaScript as well as a variety of frameworks. You can create a wrapper component for your framework of choice and start using Editor.js or you can use other’s wrapper components. Some of the most popular Editor.js wrapper components are listed below:

  1. Ngx-EditorJS for Angular

  2. vue-editor-js for Vue

  3. react-editor-js for React

I will be setting up and configuring Editor.js with vanilla JavaScript in this tutorial.

Getting started

You can install the Editor.js via NPM using the npm i @editorjs/editorjs — save or load via CDN. Besides these, you can also manually load the files into your project. If you don’t have NPM installed, the official documentation has got you covered.

I will be loading the Editor.js using CDN but feel free to use NPM for a more robust setup.

To load from CDN, we have to add the following line in your main HTML file between the head tags.

<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>

Our HTML file should look something like this:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>EditorJS Demo</title>
    <script        src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
    <link rel="stylesheet" href="style.css">
</head>

<body>
    <h1>EditorJS</h1>
    <div class="container">
        <div id="editorjs"></div>
    </div>
    <script src="./index.js"></script>
    <h1>*****</h1>
</body>

</html>

We will be using the Editor.js instance inside our div element with ID “editorjs”. We will reference this ID in our JavaScript file.

As you can see, I have added my custom CSS file called ‘style.css’ along with my own JavaScript file ‘index.js’. We will be importing and setting up Editor.js in our index.js file.

Our index.js should look like this:

const editor = new EditorJS({
    holder: 'editorjs',
 }
);

You need to pass the ID of the HTML element where you want to run the Editor.js instance into the holder property. In our case, we want to run Editor.js in our div element with ID “editorjs”, hence we have passed ‘editorjs’ to our holder property.

In my CSS file, I have centered the text to look appealing.

That’s all we need to get started with Editor.js!

Here is what our editor looks like so farHere is what our editor looks like so far

Configuring Tools

Editor.js gives us many tools that we can load and configure manually. By default, only Text comes preinstalled. We will be installing the following tools in this tutorial:

  1. Header

  2. Paragraph

  3. Simple-Image

  4. Embed

  5. Delimiter

Embed provides support for the embedded content from services such as YouTube, Twitter, Gycat, etc. You can find a detailed list here. Simple-Image is the name of a tool that enables rendering images by just pasting the image’s URL.

It is worth noting that if you want to upload images from your local device to the editor, you will need a different tool. You can use the Image tool to render content you upload as well as render images by just pasting their URL.

The reason I am showcasing Simple-Image in this article instead of the Image tool is primarily that the Image Tool requires a backend service to receive the uploaded image and return a URL endpoint for the same. The Github repository explains this in-depth.

There are a lot more than these such as warning, quotes, audio, table, and much more. You can find the entire list with instructions on Github.

We will be using CDN to load all the tools I have listed above. After adding, our HTML file should look like this:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>EditorJS Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
    <script src="https://cdn.jsdelivr.net/npm/@editorjs/header@latest"></script>
    <script src="https://cdn.jsdelivr.net/npm/@editorjs/paragraph@latest"></script>
    <script src="https://cdn.jsdelivr.net/npm/@editorjs/simple-image@latest"></script>
    <script src="https://cdn.jsdelivr.net/npm/@editorjs/embed@latest"></script>
    <script src="https://cdn.jsdelivr.net/npm/@editorjs/delimiter@latest"></script>
    <link rel="stylesheet" href="style.css">
</head>

<body>
    <h1>EditorJS</h1>
    <div class="container">
        <div id="editorjs"></div>
    </div>
    <script src="./index.js"></script>
    <h1>*****</h1>
</body>

</html>

And our index.js should look like the following:

const editor = new EditorJS({
    holder: 'editorjs',

/** 
     * Available Tools list. 
     * Pass Tool's class or Settings object for each Tool you want to use 
     */
   tools:{
       header:Header,
       delimiter: Delimiter,
       paragraph: {
        class: Paragraph,
        inlineToolbar: true,
      },
      embed: Embed,
      image: SimpleImage,
   }
}
);

It is very easy to add more such tools to our editor. We have to install or load them via npm or CDN and then just pass them in our ‘tools’ property as I have done above.

That’s literally all we needed to get our Editor.js up and running with selected tools.

Our editor with all the plugins we installed.Our editor with all the plugins we installed.

Persisting Data

What’s the use of editor if we can’t store and persist the data?

As stated earlier, Editor.js outputs clean, JSON data. To retrieve this data, we can call the save() method on the Editor.js instance. It will return a Promise that resolves with clean data. We can store this data in our database then. For now, I will log the data in our console.

First, we need to create a function that we can call to get and save the data of the editor. Add the following function at the bottom of the index.js file:

function myFunction(){
    editor.save().then((output) => {
        console.log('Data: ', output);
    }).catch((error) => {
        console.log('Saving failed: ', error)
    });
}

But adding function isn’t enough. We need a button to call the function. I have added a button to my HTML file in the following manner:

<div  onclick="myFunction()" class="btn">Save</div>

Besides this, I have also styled the button using CSS.

.btn{
    text-align: center;
    align-items:center;
    justify-content: center;
    display: flex;
    background:rgb(119, 206, 119);
    padding:.4rem;
    width:20%;
    margin:auto;
    border-radius: 8px;
    color:white;
    cursor: pointer;
}
.btn:hover{
    background:rgb(17, 170, 17);
}

Now are all set to see our data in the console.

Data gets logged into the browser’s consoleData gets logged into the browser’s console

Although I have logged the data to the console, you can send this data to your database. As we can see, the data is in JSON format. Therefore, it can easily be stored in the database. Additionally, you can perform the sanitization of the data before storing it as well.

Conclusion

From writing a personal description to filling out details of a product, rich-text editors are required in almost every application that takes input. Editor.js provides a feature-rich editor that not only looks clean but also produces clean data.

At the time of writing this article, the latest version of Editor.js available is 2.18 but the next version, 2.19, is expected to be released soon. The next version will add the much-awaited read-only mode to Editor.js, thus eliminating the need for creating custom renderers.

You can find the complete guide to Editor.js on their official website. Additionally, you can find all the code I have used in this article on Github.

Did you find this article valuable?

Support Smart Dev Blogs by becoming a sponsor. Any amount is appreciated!