Flask, WTForms, and Quill

A small recipie for combining WTForms and the Quill text editor.

Premise

I’m using Flask-WTF so this isn’t exactly the same as a pure WTForms implementation, but it should get anyone else on the right track.

The Quill text editor defines its contents as a delta object.

“Don’t be confused by its name Delta—Deltas represents both documents and changes to documents.”

When a user submits the “save changes” button we can use the Quill API to access the contents of the text editor, serialize it with JSON.stringify(), put that string in a WTForm field, which then gets submitted to the backend. In order to keep the form nice and clean we can hide that field from the user.

Example Code

forms.py

from flask_wtf import FlaskForm
from wtforms import SubmitField, HiddenField, IntegerField
from wtforms.validators import Length, NumberRange
from wtforms.widgets import HiddenInput

class CreatePost(FlaskForm):
    delta = HiddenField(
        'delta',
        validators=[Length(0, 255)],
    )
    
    content_length = IntegerField(
        label='',
        validators=[
            NumberRange(2, 255, "Blank posts aren't very interesting.")
        ],
        widget=HiddenInput()
     )
     
    submit = SubmitField('Create Post')

template.html

This flask template takes an argument named “form” containing a CreatePost object (defind in the example code above).

{% block page_content %}
<div class="row justify-content-center">
  <div class="my-sm-2">
    <div class="page-header">
      <h1>Read a Post</h1>
    </div>
    <!-- Create the editor container -->
    <div id="editor">
      <p>Hello World!</p>
      <p>Some initial <strong>bold</strong> text</p>
      <p><br></p>
    </div>

    <!-- 
    Form submission is handled by FlaskWTF. It has a hidden field, which
    is updated with the contents of quill.getContents() when the submit
    button is pressed
    -->
    {{ render_form(form) }}

    <!-- Include the Quill library -->
    <script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>

    <script>
	   // Initialize the Quill editor
      var quill = new Quill('#editor', {
        theme: 'snow'
      });

      // When the submit button is pressed, retrieve several pieces of info
      // from the QuillJS API (https://quilljs.com/docs/api/#content), copy
      // them into to WTForms hidden fields, and submit the form
      var submit_entry = function () {
      
        // Get the contents of the text editor
        var hidden_text_field = document.getElementById('delta');
        hidden_text_field.value = JSON.stringify(quill.getContents());
        
        // Get the length of the contents of the text editor
        var hidden_length_field = document.getElementById('length');
        hidden_length_field.value = quill.getLength();
      }

      // Attach the onclick function to the submit button Flask-WTF creates
      var new_post_form = document.getElementsByClassName('form')[0];
      new_post_form.onsubmit = submit_entry;

    </script>
  </div>
</div>
{% endblock %}