Offering Configuration Options for a Custom Views Plugin in Drupal 8


In the previous post, we discussed how to write a style plugin for Views in Drupal 8. In this post, we will see how to allow the user to configure our style plugin.

We had previously created a class named CardsStyle for the plugin. In order to add configuration options, we will need to extend that class with two new method: buildOptionsForm and defineOptions as follows.

namespace Drupal\mymodule\Plugin\views\style;

use Drupal\views\Plugin\views\style\StylePluginBase;
use Drupal\Core\Form\FormStateInterface;

class CardsStyle extends StylePluginBase {

  /**
   * Builds the configuration form.
   */
  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    parent::buildOptionsForm($form, $form_state);

    $form['padding'] = array(
      '#type' => 'select',
      '#title' => $this->t('Padding'),
      '#description' => $this->t('The amount of padding inside the cards.'),
      '#default_value' => $this->options['padding'],
      '#options' => array(
        'thin' => $this->t('Thin'),
        'thick' => $this->t('Thick'),
      ),
    );
  }

  /**
   * Defines default values.
   */
  protected function defineOptions() {
    $options = parent::defineOptions();
    $options['padding'] = array('default' => 'thin');
    return $options;
  }
}

In buildOptionsForm, we add our options to the configuration form - in this case, the only option will be to specify the padding in the card items. This works just like a form callback; we can add our fields to the $form array the Form API way. The form default values will be available in $this->options. The $form_state argument is an object of the FormStateInterface class in Drupal 8, and not an array any more. To avoid errors, we need to add a use statement at the top to ensure that this class is loaded. 

By overriding the defineOptions method, we can declare the available options and their default values. In both methods, we need to call the parent implementation to retain all existing functionality. Note that the t() function is made available as an object method, so we can use $this->t() to translate strings.

Opening up a view that uses the custom style plugin, we will now see the options defined above in the configuration panel. 

Now that we have the option available to the user, we need to make use of the selected value. A preprocess function can be used to retrieve the selected value and make it available to the template - or do further processing based on it. If you recall, the theme was called mymodule_cards_style, so the preprocess function should be named template_preprocess_mymodule_cards_style.

function template_preprocess_mymodule_cards_style(&$variables) {
  $view = $variables['view'];
  $variables['padding'] = $view->style_plugin->options[‘padding'];
}

In the preprocess function, the view object's style_plugin property gives us access to the style plugin object. This, in turn, will expose the active configuration in its options property as an array. This preprocessor copies this value into $variables, which will be available in the template file. The new variable can be used, for instance, to assign appropriate classes in the template, as the updated template file illustrates below.

{% for row in rows %}
  <div class="card-container card-{{ padding }}">
    <div>{{ row }}</div>
  </div>
{% endfor %}