Search code examples
djangodjango-templatesckeditorhtmx

ckeditor not saving changes django


I have a form where in one of the fields, I use the ckeditor. However when I submit the form, the changes in the ckeditor field is not being saved. In the model, I have changed the field to aRichTextField. I have installed "ckeditor" in my apps in settings as well.

I have also both tried to load these scripts in my template:

{% load static %}

<script type="text/javascript" src="{% static "ckeditor/ckeditor-init.js" %}"></script>
<script type="text/javascript" src="{% static "ckeditor/ckeditor/ckeditor.js" %}"></script> 

On top of that have I also tried to add the {{ form.media }} instead of the scripts but it does still not work.

I am using HTMX to dynamically update the form.

This is my form template right now

<form action='' method="POST" class="form" hx-post='' hx-swap='outerHTML'>
    {% csrf_token %}
    {{ form.media }}
    <div class="form-group">
    {% for field in form %}
            {{ field }}
     </div>
    {% endfor %}
    
   
    <br>

    <div class='htmx-indicator'>Loading...</div>
    <div class="text-center">
        <button class='htmx-inverted-indicator' type='submit' >Save</button>
      </div>
    
    {% if message %}
        <p>{{ message }}</p>
    {% endif %}
    
</form>

Does anybody know why the form is not being saved?

EDIT This is my view

@login_required
def book_update_view(request, id=None):
    book = get_object_or_404(Book, id=id)
    form = BookForm(request.POST or None, instance=book)
       context = {
        "form": form,
         "object": book,
     }
    if form.is_valid():
         form.save()
         context['message'] = 'Saved!'
    if request.htmx:
        return render(request, "book/snippets/forms.html", context)
    return render(request, "book/update.html", context)  

Solution

  • Looks like there is a conflict between the CKEditor and HTMX. The below relies heavily on this answer. It makes the following changes:

    • Switches the HTMX labels to the button rather than the form

    • Applies an event listener to the CKEditor - it does this via the {{field.label_tag}} which is now included

    • Fixes up a misplaced tag

    Try making your form something like this (don't forget to replace the name of the CKEditor field - you may need to check your source code to see how this is rendered):

    <form method="post">
    {% csrf_token %}
    {{ form.media }}
    
    <script>
    document.body.addEventListener('htmx:configRequest', (event) => {
        var element = new CKEDITOR.dom.element( document.getElementById( '{{ form.NAMEOFCKEDITORFIELD.id_for_label }}' ) );
        event.detail.parameters['{{ form.NAMEOFCKEDITORFIELD.html_name }}'] = element.getEditor().getData();        
    })
    </script>
    <div class="form-group">
    {% for field in form %}
            {{ field.label_tag }}:<br />{{ field }}
    
    {% endfor %}    
     </div>
    <br>
    
    <div class='htmx-indicator'>Loading...</div>
    <div class="text-center">
        <button class='htmx-inverted-indicator' type='submit' hx-post="{% url 'book_update_view_name' book.id %}" hx-target="#{{form.id}}" hx-swap="outerHTML">Save</button>
      </div>
    
    {% if message %}
        <p>{{ message }}</p>
    {% endif %}