1

Was wondering if it is possible to add a custom button within a Wagtail model page that will allow me to save (create) the current data fields and move on to another page. The "save and add another" button was already available in django and I want to have something like that on the Wagtail model page.

Thanks.

Idea on how I want it to be

Heroo
  • 97
  • 8
  • Is this Wagtail's modeladmin or a snippet page? If it is snippets would you be happy with a modeladmin based solution (the Wagtail's modeladmin) https://docs.wagtail.io/en/stable/reference/contrib/modeladmin/index.html – LB Ben Johnston Jan 23 '22 at 10:31
  • Sorry. The question may not have been clear. What I was asking is are you using Snippets or ModelAdmin in the screenshot shown? – LB Ben Johnston Jan 27 '22 at 11:08
  • Yeah I was using ModelAdmin. – Heroo Jan 27 '22 at 11:27

1 Answers1

0

Wagtail has a few ways to customise content that is shown in the various Wagtail modeladmin views.

Code Example

Step 1 - create a custom CreateView

  • This will override the get_context_data method to provide the create_url, we could do this simpler (the context already has access to the instance) but it is nice to be explicit.
  • Override the get_success_url method to allow for a URL param of next to be set, if that exists the next URL will be this instead of the default behaviour.

products/wagtail_hooks.py

from wagtail.contrib.modeladmin.views import CreateView
# ... other imports


class CustomCreateView(CreateView):

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['create_url'] = self.create_url
        return context

    def get_success_url(self):
        next = self.request.GET.get('next')
        if next:
            return next
        return super().get_success_url()

class ProductsModelAdmin(ModelAdmin):
    create_view_class = CustomCreateView

Step 2 - Override the template to add a new button

  • Wagtail modeladmin uses a template path override approach, you will need to create a new template that aligns with your desired override (for example we may just want to override the product model create view only.
  • templates/modeladmin/products/products/create.html -> this says to override the create template for the products model within the products app.
  • Add the code below and check it is working, sometimes the templates path can be a bit tricky so ensure you can see the new button AND that the button has the data-next attribute that should be your create URL.

templates/modeladmin/products/products/create.html

{% extends "modeladmin/create.html" %}
{% load i18n wagtailadmin_tags %}

{% block form_actions %}
  {{ block.super }}
  <div class="dropdown dropup dropdown-button match-width">
    <button type="submit" class="button button-secondary action-save button-longrunning" data-next="{{ create_url }}" data-clicked-text="{% trans 'Saving…' %}">
      {% icon name="spinner" %}<em>{% trans 'Save & add another' %}</em>
    </button>
  </div>
{% endblock %}

Step 3 - Add JS to modify the form action URL on click

  • The next step requires a bit of JavaScript, we want to attach a different behaviour to the 'save and add another' button.
  • The JS used here does not require jQuery and should work in IE11
  • Once the DOM is loaded (which means JS can do things), find all the buttons with the data-next attribute.
  • Add a listener to the 'click' of each of those buttons which will dynamically update the form action attribute with the extra URL part.
  • This extra URL part gets read by the get_success_url method in the custom create class but only on a successful save, otherwise you will stay on the page and be able to fix errors.
{% block extra_js %}
{{ block.super}}
<script>
  document.addEventListener('DOMContentLoaded', function() {
    document.querySelectorAll('[data-next]').forEach(function(button) {
      button.addEventListener('click', function(event) {
        var form = document.querySelector('.content-wrapper form');
        form.action = form.action + '?next=' + button.dataset.next;
      });
    });
  })
</script>
{% endblock %}
LB Ben Johnston
  • 4,751
  • 13
  • 29