How to add default fields on creation to Wagtail form builder pages

Viewed 36

I have created job application form with Wagtail form builder. Now I need to add some fields which are meant to be constant and appear on the application form without the need for the admin user adding them each time a new job application form is created.

For instance, I have the following: Name Email Phone Number [admin created form fields]

How to instantiate the first 3 fields and populate FormField db table with the data before the JobApplicationForm page is created?

My data as below:

FormField(
    question   = 'Enter Your Name',
    label      = 'name',
    field_type = 'singleline',
    required   = True,
    ),

I have the feeling a signal has to be created, but I don't know how?

1 Answers

This solution assumes you want to pre-create 'placeholder' form fields once the user goes to create a new form page. The user will be able to easily edit/remove or adjust these but will not have to manually create these fields every single time they go to create a new form page.

You could allow FormFields to be related to any Page, or create a 'FormFieldTemplate' model, this will be connected to your Form Page Index model, allowing users to create / manage the default fields created.

From here, you can use the Wagtail ability to customise generated forms by overriding the base_form_class.

Then you can adjust the initial 'empty' InlinePanel entries created.

Note: This approach does not add new fields by default, but merely adds them to the create form by default. Once the first save happens, they will the be on the model. Subsequent edits will preserve whatever edits happen to those fields.

If instead you want to add fields that are presented on the form builder but not actually editable by page editors see this answer https://stackoverflow.com/a/47303659/8070948

Example

from wagtail.admin.forms import WagtailAdminPageForm
# .. other imports



class JobListingsIndexPage(Page):
    content_panels = Page.content_panels + [
        # any default form fields added to the parent will be automatically included on create (copied) to child pages
        InlinePanel('form_fields', label="Default form fields"),
    ]

    subpage_types = [FormPage]


class FormField(AbstractFormField):
    # adjust the `ParentalKey` to be generic to all `Page` models, not just the form page one
    page = ParentalKey(Page, related_name='form_fields', on_delete=models.CASCADE)


class FormPageForm(WagtailAdminPageForm):
    
    def __init__(self, *args,**kwargs):

        super().__init__(*args, **kwargs)

        # only adjust the create form - setting default placeholder fields based on parent's form fields
        if not self.instance.pk:
            # leverage the min_num (empty) formsets to inject initial data into X empty forms
            # ensure we honour any existing `min_num` already set by adding them
            default_fields = self.parent_page.form_fields.values()
            self.formsets['form_fields'].min_num = len(default_fields) + self.formsets['form_fields'].min_nu
            for index, form in enumerate(self.formsets['form_fields'].forms):
                form.initial = default_fields[index]


class FormPage(AbstractEmailForm):
    # ... fields / panels etc
    base_form_class = FormPageForm
Related