Extending EBT Settings form

08/02/2023, by Ivan

Create new EBT Settings form class

I heard from many programmers worries about number of settings for EBT modules: DOM Box, background, borders, classes, etc. These programmers implied that content editors will be confused or in another way will be encouraged to do drastically different blocks, margins, backgrounds. Some projects needs flexibility and more settings for content editors, but some projects have pretty strict story books with components. For this case we need to change our EBT Settings field widget. 

Also if you create a new EBT module and attached javascript plugin with options, you will need to use own EBT settings widget with setting fields for these options.

EBT Core module has EbtSettingsDefaultWidget class for EBT Settings field widget. It contains DOM Box, background and all other settings. Let's start to create a new class EbtSettingsSimpleWidget (I will put it in EBT Core module). It will contain only three settings Width, Spacing (for margin below block).

Create a new file:
/src/Plugin/Field/FieldWidget/EbtSettingsSimpleWidget.php

<?php

namespace Drupal\ebt_core\Plugin\Field\FieldWidget;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\ebt_core\Plugin\Field\FieldWidget\EbtSettingsDefaultWidget;

/**
 * Plugin implementation of the 'ebt_settings_simple' widget.
 *
 * @FieldWidget(
 *   id = "ebt_settings_simple",
 *   label = @Translation("EBT Simple settings"),
 *   field_types = {
 *     "ebt_settings"
 *   }
 * )
 */
class EbtSettingsSimpleWidget extends EbtSettingsDefaultWidget {

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $element = parent::formElement($items, $delta, $element, $form, $form_state);


    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
    foreach ($values as &$value) {
      $value += ['ebt_settings' => []];
    }

    return $values;
  }

}

We will extend our basic settings class EbtSettingsDefaultWidget. In annotation comment @FieldWidget we will name our widget id = "ebt_settings_simple" and label = @Translation("EBT Simple settings")

/**
 * Plugin implementation of the 'ebt_settings_simple' widget.
 *
 * @FieldWidget(
 *   id = "ebt_settings_simple",
 *   label = @Translation("EBT Simple settings"),
 *   field_types = {
 *     "ebt_settings"
 *   }
 * )
 */

We also have two method formElement(), massageFormValues(). You can leave massageFormValues() as it is. Drupal will automatically serialize all settings in one field field_ebt_settings. So it doesn't matter how many settings you have, they will store as serialized array and you need only specify settings fields with Form API:

https://www.drupal.org/docs/drupal-apis/form-api

In formElement(), we will define setting fields. Let's hide DOM Box and border settings:

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $element = parent::formElement($items, $delta, $element, $form, $form_state);
    unset($element['ebt_settings']['design_options']['box1']);
    unset($element['ebt_settings']['design_options']['other_settings']['border_color']);
    unset($element['ebt_settings']['design_options']['other_settings']['border_style']);
    unset($element['ebt_settings']['design_options']['other_settings']['border_radius']);


    return $element;
  }

If you apply new field widget for one of your EBT block types:

EBT Settings

You will see smaller settings form:

Without Border fields

Now we will remove background settings too. If you need background settings and don't need all other settings, you can extend EbtSettingsDefaultWidget class and create own field widget. Here is example how to make EBT Settings small as possible.

...
    unset($element['ebt_settings']['design_options']['other_settings']['background_color']);
    unset($element['ebt_settings']['design_options']['other_settings']['background_media']);
    unset($element['ebt_settings']['design_options']['other_settings']['background_image_style']);
...

Our form is already have only two settings:

only 2 fields

It's remaining only to add Spacing field for adding margin to the bottom. We will use additional classes and CSS to organize spacings:

spacing-none
spacing-sm
spacing-md
spacing-lg
spacing-xl
spacing-xxl 

Maybe you will need for larger list of spacing, feel free to extend EbtSettingsSimpleWidget class and create own field widget class from it as we did with EbtSettingsDefaultWidget class.

    $element['ebt_settings']['design_options']['other_settings']['spacing'] = [
      '#type' => 'select',
      '#title' => $this->t('Background Image Style'),
      '#options' => [
        'spacing-none' => $this->t('None'),
        'spacing-sm' => $this->t('Small'),
        'spacing-md' => $this->t('Medium'),
        'spacing-lg' => $this->t('Large'),
        'spacing-xl' => $this->t('Extra Large'),
        'spacing-xxl' => $this->t('Double Extra Large'),
      ],
      '#default_value' => $items[$delta]->ebt_settings['design_options']['other_settings']['spacing'] ?? 'spacing-none',
    ];

Now I see three ways to add styles for our block:

1. Override block template and set spacing there as block class.

2. Generate styles on fly and include them as custom CSS styles for each block.

3. Add class with javascript by generating custom javascript for each EBT block.

4. Override list of classes in template_preprocess_block() function.

All of this approaches will work, but I think it will be easier to use template_process_block() function. At least we already have ebt_core_preprocess_block() function in ebt_core.module file. Let's use it:

...
  if (!empty($ebt_settings[0]['ebt_settings']['design_options']['other_settings']['spacing'])) {
    $variables['attributes']['class'][] = $ebt_settings[0]['ebt_settings']['design_options']['other_settings']['spacing'];
  }
...

EBT minimal settings

Space for EBT blocks

Now we pass Spacing field keys as class names and we will use CSS to define value for margins based on these classes:

/ebt_core/scss/ebt_core.scss

.spacing-sm {
  margin-bottom: 10px;
}

.spacing-md {
  margin-bottom: 20px;
}

.spacing-lg {
  margin-bottom: 30px;
}

.spacing-xl {
  margin-bottom: 40px;
}

.spacing-xxl {
  margin-bottom: 50px;
}

You can override values in your custom CSS file, for example using any class from content or body tag:

body .spacing-sm {
  margin-bottom: 15px;
}

And you can override list of spacings in your custom class for EBT settings field widget.

That's it, now you can choose between DOM Box and plain select box for setting margins for your EBT blocks.

Feel free to ask about EBT modules on Drupal.org or contact form:

Contact

Create an issue on Drupal.org

Keep in touch on LinkedIn