React/ReactJS: Rich Text Editor

A Rich Text Editor is an interface for editing rich text, which is a formatted text supporting various styles (bold, italics, underline), colours, font families and font sizes. There can also be paragraphs, header elements, line spacing and tab-widths. You can also add hyperlinks, images, videos and audio clips. The toolbar contains an array of icon menus.

Currently, there are many Rich Text Editors available for ReactJS. For this tutorial, I picked react-quill, a Quill component for ReactJS. Quill is a free and open source API driven Rich Text Editor. You can use it freely for your personal or commercial projects.

reactjs quill

Install the Quill component for ReactJS.

					
						npm i react-quill --save
					
				

Setting-up Quill in ReactJS

Import the Quill component for ReactJS, along with the themed style-sheets associated with it: quill.snow.css and quill.bubble.css.

						
							import ReactQuill from 'react-quill';
							import 'react-quill/dist/quill.snow.css';
							import 'react-quill/dist/quill.bubble.css';
						
					

Now we set the toolbar module, one which will allow us to format the entered text. The toolbar module allows us to pick which all formatting options to offer in the menu using an array of formatted names. The list of all formatting options available in Quill can be checked here.

Here we pick the basic formatting options like font family (Sans Serif, Serif, Monospace), font sizes (small, normal, huge, large), styles (bold, italic, underline), lists (ordered, numbered), alignment (left, middle, right) and colours. There will also be one clear format icon.

We set this all up inside the constructor() function.

						
					  	constructor(props) {
							super(props);
							
							this.modules = {
								toolbar: [
							      [{ 'font': [] }],
							      [{ 'size': ['small', false, 'large', 'huge'] }],
							      ['bold', 'italic', 'underline'],
							      [{'list': 'ordered'}, {'list': 'bullet'}],
							      [{ 'align': [] }],
							      [{ 'color': [] }, { 'background': [] }],
							      ['clean']
							    ]
							};

							this.formats = [
							    'font',
							    'size',
							    'bold', 'italic', 'underline',
							    'list', 'bullet',
							    'align',
							    'color', 'background'
						  	];
						}
						
					

The <ReactQuill/> Module

Now, before embedding the <ReactQuill/> component, one very important thing to consider is how to get the typed texts (along with the mark-up tags and given inline styles). Most probably they have to be stored somewhere in a database. The typed and formatted rich texts can be accessed from the handler attached to the onChange event, which actually is a props now. Also we will need to set a state variable to store the formatted texts temporarily; we will call it comments.

The handler is named rteChange() for our example.

						
                       	<ReactQuill onChange={this.rteChange}/>
						
					

The onChange props has four parameters: content, delta, source and editor. The contents parameter straight away gives the HTML, i.e., the formatted text along with all the associated tags and inline styles. The delta object expresses the change and the source object contains the soure of the change. And finally, the editor parameter which is a read-only proxy to useful editor accessors like getHTML() (returns the full HTML text), getLength() (returns the number of typed characters without tags), getText() (returns the plain text without mark-up tags), etc. You can check the full list here.

Below we do console.log() of getHTML(), getLength() and getText().

						
					  	constructor(props) {
							super(props);
							...
							...
							this.state = {
								comments: ''
							}

							this.rteChange = this.rteChange.bind(this);
						}

						rteChange = (content, delta, source, editor) => {
							console.log(editor.getHTML()); // HTML/rich text
							console.log(editor.getText()); // plain text
							console.log(editor.getLength()); // number of characters
						}
						
					

The theme attribute lets you choose an available theme; here we choose the "snow" theme (which is also the default). The "bubble" theme is tooltip-based and will not be intuitive where to type unless you do some custom styles for borders and background of the editor. The modules and formats props were given the values which were earlier set inside the constructor. The typed comments can be accessed from the handler attached to the onChange props, along with all the formatted tags and inline CSS styles.

						
                       	<ReactQuill theme="snow" modules={this.modules} 
                       		 formats={this.formats}  onChange={this.rteChange} 
                       		 value={this.state.comments || ''}/>
						
					
reactjs quill basic toolbar

Here is the entire complete component.

						
						import React, { Component } from 'react';
						import ReactQuill from 'react-quill';
						import 'react-quill/dist/quill.snow.css';
						import 'react-quill/dist/quill.bubble.css';

						class RichTextEditor extends Component {
							constructor(props) {
								super(props);
								
								this.modules = {
									toolbar: [
								      [{ 'font': [] }],
								      [{ 'size': ['small', false, 'large', 'huge'] }],
								      ['bold', 'italic', 'underline'],
								      [{'list': 'ordered'}, {'list': 'bullet'}],
								      [{ 'align': [] }],
								      [{ 'color': [] }, { 'background': [] }],
								      ['clean']
								    ]
								};

								this.formats = [
								    'font',
								    'size',
								    'bold', 'italic', 'underline',
								    'list', 'bullet',
								    'align',
								    'color', 'background'
							  	];

							  	this.state = {
									comments: ''
								}

								this.rteChange = this.rteChange.bind(this);
							}

							rteChange = (content, delta, source, editor) => {
								console.log(editor.getHTML()); // rich text
								console.log(editor.getText()); // plain text
								console.log(editor.getLength()); // number of characters
							}

							render() {
							    return (
							      <div>
							        <ReactQuill theme="snow"  modules={this.modules} 
										formats={this.formats} onChange={this.rteChange} 
									value={this.state.comments || ''}/>
							      </div>
							    );
							}

						}

						export default RichTextEditor;
						
					

We type a sample line into the text editor and do some formatting around its words.

reactjs quill sample text

Below are the respective outputs of editor.getHTML(), editor.getText() and editor.getLength() into the browser console.

reactjs quill console

Notes

  • The bubble theme is tooltip-based. And if you have a white background on your page you will not be able to make out the editing area; write some custom styles for the border/background.
    reactjs quill bubble theme
  • React-Quill is MIT licensed.