Building a Configuration Form for a Custom Panels Plugin

In my previous post, we built a custom Panels plugin that shows a node status icon to indicate whether the node is published or unpublished. This time around, we will enhance that plugin by introducing a configuration form. For the sake of demonstration, we will add a setting that lets the user choose when they want the show the status icon: only when the node is unpublished, or always.

As one might expect, we will need to use Drupal's From API to define the configuration options. First, we need to tell Panels which function to call when it shows the configuration form. This can be done by adding an 'edit from' item in the $plugin definition array. The following snippet shows the update array.

$plugin = array(
  'title' => t('My Panel - Title with status indicator'),
  'description' => t('Shows the title and the published/unpublished icon.'),
  'category' => t('Custom'),
  'render callback' => 'my_panel_status_pane_render',
  'all contexts' => TRUE,
  'edit form' => 'my_panel_status_pane_edit_form',
);

Once we make this change, a 'Settings' option will appear in the contextual menu of our custom pane.

Pane context menu

Our form callback will be called my_panel_status_pane_edit_form(). Let’s implement that function. The only form element we need is a dropdown box with two options: 'Always' and 'Only when unpublished'.

/**
 * Pane configuration form builder.
 */
function my_panel_status_pane_edit_form($form, &$form_state) {
  $conf = $form_state['conf'];

  $form['indicators'] = array(
    '#type' => 'select',
    '#title' => t('Displayed indicators'),
    '#default_value' => !empty($conf['indicators']) ? $conf['indicators'] : 'always',
    '#options' => array(
      'always' => 'Always',
      'unpublished_only' => 'Only when unpublished',
    ),
  );

  return $form;
}

Panels will pass us the currently saved configuration in $form_state['conf'], so we can use that to set the default value. The form submission is not handled automatically, so we need to implement the submit handler as well. The submit handler's name needs to conform to Drupal standards and it needs to be the form callback's name followed by '_submit' - in our case, this will be 'my_panel_status_pane_edit_form_submit'.

/**
 * Pane configuration submit handler.
 */
function my_panel_status_pane_edit_form_submit($form, &$form_state) {
  $values = $form_state['values'];
  $form_state['conf']['indicators'] = $values['indicators'];
}

Even though it is not fully automatic, Panels does provide a saving mechanism for the configuration. All we need to do is copy the submitted value to $form_state['conf']. Panels will take care of saving and later retrieving the value. 

Now, the render function needs to take the selected option into consideration. If you take a look at the previous post, the render function receives an argument named $conf. This variable will contain the configuration we have saved into it in the form submit handler. Let's update the render function so that it doesn't insert the status icon if the node is published and the pane is configured to only show it when the node is unpublished. The updated parts of the render function are shown below.

function my_panel_status_pane_render($subtype, $conf, $args, $context) {
  [...]

  // Select which icon to show.
  if ($node->status && $conf['indicators'] == 'always') {
    $indicator = '<i class="fa fa-unlock"></i>' ;
  }
  elseif (!$node->status) {
    $indicator = '<i class="fa fa-lock"></i>' ;
  }
  else {
    $indicator = '';
  }

  [...]
}

And we are done. We have a custom Panels plugin that offers the following configuration form.

Pane settings