How Can I Apply ToastUI Editor in Django Application?

210 Views Asked by At

Has anyone heard of ToastUI Editor? It's so difficult to find resource concerning it.

With Django ModelForm, I am trying to use ToastUI Editor as form's content field. I have implemented it through JS, but I am trying to find more pythonic and simpler way to do it.

Here's how I have implemented it:

base.html

<!DOCTYPE html>
<html lang="en">
<head>
  ...
  {# ToastUI #}
  <link rel="stylesheet" href="https://uicdn.toast.com/editor/latest/toastui-editor.min.css" />
</head>
<body>
  ...
  
  {# ToastUI #}
  <script src="https://uicdn.toast.com/editor/latest/toastui-editor-all.min.js"></script>
</body>
</html>

create.html

{% extends 'base.html' %}

{% block content %}
<form id="journal-form" action="{% url 'notes:create' %}" method="post" enctype='multipart/form-data'>
  {% csrf_token %}

  {% with journal_form.title as title %}
  <div class="form-group">
    <label for="{{ title.id_for_label }}">{{ title.label }}</label>
    <input type="{{ title.field.widget.input_type }}" class="form-control" id="" placeholder="{{ title.label }}" name="{{ title.name }}" />
  </div>
  {% endwith %}

  {% with journal_form.content as content %}
  <div class="form-group" style="display: none;">
    <label for="{{ content.id_for_label }}">{{ content.label }}</label>
    <textarea id="{{ content.id_for_label }}" class="form-control" placeholder="{{ content.label }}" name="{{ content.name }}"></textarea>
  </div>
  {% endwith %}
  <div id="editor"></div>
  <div>
    {{ journal_image_form.as_p }}
  </div>
  <button type="submit" class="btn btn-primary">Create</button>
</form>
<script>
  document.addEventListener('DOMContentLoaded', (event) => {
    const editorDiv = document.getElementById('editor');
    const editor = new toastui.Editor({
      el: editorDiv,
      height: '500px',
      initialEditType: 'markdown',
      previewStyle: 'vertical',
      initialValue: editorDiv.value,
    })
    const journalForm = document.getElementById('journal-form')
    journalForm.addEventListener('submit', (e) => {
      e.preventDefault()
      const journalFormTextArea = document.querySelector('textarea')
      journalFormTextArea.textContent = editor.getMarkdown()
      journalForm.submit()
    });
  });
</script>
</script>
{% endblock content %}

As you can see, I am using two textareas; one for the form, another for UI. When the form is submitted, JS code grabs what is written in ToastUI Editor and hand it to the form.

I have also found that there is a package for this, called 'django-tuieditor'. With that installed, I have modified forms.py and models.py:

forms.py

...

from django_tuieditor.widgets import MarkdownEditorWidget
from django_tuieditor.fields import MarkdownFormField

class JournalForm(forms.ModelForm):
    content = MarkdownFormField(
        widget=MarkdownEditorWidget(),
    )
    class Meta:
        model = Journal
        fields = ('title', 'content')

models.py

...
from django_tuieditor.models import MarkdownField

# Create your models here.
class Journal(models.Model):
    title = models.CharField('title', max_length=255)
    content = MarkdownField('content')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

setting

INSTALLED_APPS = [
    ...
    'django_tuieditor'
    ...
]

This does not work. Nothing changes without JS code.


Compare to SimpleMDE which allows much simpler JS code.

  ...

  {% with journal_form.content as content %}
  <div class="form-group my-3">
    <label for="{{ content.id_for_label }}">{{ content.label }}</label>
    <textarea id="editor" class="form-control" placeholder="{{ content.label }}" name="{{ content.name }}"></textarea>
  </div>
  {% endwith %}

  ...

<link rel="stylesheet" href="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css">
<script src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
<script>
  document.addEventListener('DOMContentLoaded', (event) => {
    const contentTextarea = document.querySelector('#editor');
    const editor = new SimpleMDE({
      element: contentTextarea,
      autofocus: false,
    })
  })
</script>
...

How can I achieve this in more pythonic way or at least with much simpler JS code? How does django ModelForm/Form recognize which input goes to which field?

1

There are 1 best solutions below

2
On

A lot of that JS code for toast should be handled by the django-tui module, but the install documentation is a little lacking.

The most obvious thing to try is to include {load static} somewhere in your template page - this is to load the static JS pages included in the module that make the new field type work. With that you should be able to remove your link and script tags from your <head> and the eventListener tags from your body. Try this with just {{form.as_div}} to see if it works, then look at customising the form fields as required.