Plugin-Design: how to best add custom data to a form?

I’m trying to write a plugin for the following scenario:

  • Via Admin, I want the user to be able to curate a list of events
  • Each event has different fields, like title, data, location and many more
  • Visitors should be able to “subscribe” to events, via a simple form
  • Visitors need to be able to select the events they are interested in, then submit their name and e-mail address
  • The visitor’s data, including the events and the event’s details, need to be sent via email as well as saved so they can be evaluated later

The forms plugin seems generally to be a good fit; it has mail and save actions that will generally do what I’m looking for. Using the data-manager plugin allows to inspect and download the saved data, which works fine.

No matter what approach I try, I run into one or multiple of these problems:

  • Can’t add the selected event’s details to the submitted data
  • Adding the event’s details to the submitted data does not work without JavaScript
  • The solution can not easily be wired up and maintained via Admin for non-power-users

My “best” solution so far looks like this:

  • Curate a list of events in the page headers (can be exposed via blueprint)
  • Add a form to the page and make sure there is a hidden field with a known id/name
  • In a custom template, create fake “subscribe” toggles for each event
  • In the template, with JavaScript, add or remove all of the selected event’s details to the hidden form field as a JSON string
  • In the template that processes the form for email and data, have custom logic to process the JSON string accordingly

This seems like a dirty hack at best. Any suggestions as how to do this properly?

How does subscription to the event happen? Does every event have separate page with a form? In such case you could just use a hidden field with a current page URL I think. Or there are multiple events on a page and you need all the details of the event?

Hey Karmalakas, thanks for your reply. All events are displayed on the same page. You can subscribe to one, two, any number of them. They all have a toggle that you can flip, in which case they will be included when submitting the form.

From what I imagine, you’d need JS anyway to handle toggling. But I was thinking maybe some custom field could help here to fill event data :thinking: Not sure what to suggest actually

@domsson, The following is a rough example on how one can add fields dynamically to a form and process its submitted data.

  • Create new page with form: ‘user/pages/03.events/form.md’
    ---
    form:
      name: eventform
      fields:
        name:
          label: Name
          placeholder: Enter your name
          type: text
          validate:
            required: true
      buttons:
        submit:
          type: submit
          value: Submit
      process:
          # without action, 'onFormProcessed' will not be fired
          processEvents: true 
    ---
    
  • Create plugin $ bin/plugin devtools new-plugin
    Say we call it ‘eventform’
  • Subscribe to form events in ‘/user/plugins/eventform/eventform.php’:
    $this->enable([
        // Put your main events here
        'onFormInitialized' => ['onFormInitialized', 0],
        'onFormProcessed' => ['onFormProcessed', 0],
    ]);
    
  • Add new form fields in ‘onFormInitialized()’:
    public function onFormInitialized($event)
    {
      $form = $event['form'];
    
      if ($form['name'] !== 'eventform') {
        return;
      }
    
      // Get 'id' and 'title' of all events from somewhere
      $events = [
        'idEvent1' => 'Title event 1',
        'idEvent2' => 'Title event 2',
      ];
    
      $eventsField = [
        'type' =>  'checkboxes',
        'label' => 'Select events',
        'options' => [],
      ];
    
      // Add options to checkboxes field
      foreach ($events as $id => $title) {
        $eventsField['options'][$id] = $title;
      }
    
      $fields = (array) $form['fields'];
      $fields['events'] = $eventsField;
      $form->setFields($fields);
    }
    
  • Form will now look like:
    image
  • Process submitted data in ‘onFormProcessed()’:
    public function onFormProcessed($event)
    {
      $form = $event['form'];
      $action = $event['action'];
    
      if (! ($form['name'] === 'eventform' && $action === 'processEvents')) {
        return;
      }
    
      $values = $form->value();
      $events = $values['events'];
    
      // Save and mail data
    }
    
2 Likes

That’s super useful! I was experimenting with adding additional inputs via templates (using the HTML form attribute to associate them with the form), but that did not work at all. I was wondering what other ways there were to dynamically add fields - and now you laid one out for me.

I will give that I try today. Thank you very much for your detailed suggestions!