logo

额外区块类型 (EBT) - 全新的布局构建器体验❗

额外区块类型 (EBT) - 样式化、可定制的区块类型:幻灯片、标签页、卡片、手风琴等更多类型。内置背景、DOM Box、JavaScript 插件的设置。立即体验布局构建的未来。

演示 EBT 模块 下载 EBT 模块

❗额外段落类型 (EPT) - 全新的 Paragraphs 体验

额外段落类型 (EPT) - 类似的基于 Paragraph 的模块集合。

演示 EPT 模块 滚动

滚动

扩展 EPT 设置表单

02/09/2025, by Ivan

创建新的 EPT 设置表单类

我从许多程序员那里听到对 EPT 模块设置数量的担忧:DOM 盒(DOM Box)、背景、边框、类等。这些程序员认为内容编辑可能会被这些设置搞糊涂,或者在另一种情况下被“鼓励”去做出截然不同的段落、边距、背景。一些项目需要为内容编辑提供灵活性和更多设置,但也有一些项目拥有非常严格的组件式故事手册。针对这种情况,我们需要改变我们的 EPT Settings 字段小部件(field widget)。

另外,如果你创建了一个新的 EPT 模块并附带了带选项的 JavaScript 插件,你将需要使用你自己的 EPT 设置小部件,并为这些选项提供设置字段。

EPT Core 模块提供了用于 EPT Settings 字段小部件的 EptSettingsDefaultWidget 类。它包含 DOM 盒、背景和所有其他设置。现在让我们开始创建一个新的类 EptSettingsSimpleWidget(我会把它放在 EPT Core 模块中)。它将只包含三个设置:宽度(Width)、间距(Spacing,用于段落下方的外边距)。

创建新文件:
/src/Plugin/Field/FieldWidget/EptSettingsSimpleWidget.php

<?php

namespace Drupal\ept_core\Plugin\Field\FieldWidget;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Component\Utility\Color;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\ept_core\Plugin\Field\FieldWidget\EptSettingsDefaultWidget;

/**
 * Plugin implementation of the 'ept_settings_simple' widget.
 *
 * @FieldWidget(
 *   id = "ept_settings_simple",
 *   label = @Translation("EPT simple paragraph settings"),
 *   field_types = {
 *     "ept_settings"
 *   }
 * )
 */
class EptSettingsSimpleWidget extends EptSettingsDefaultWidget  {

  /**
   * {@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 += ['ept_settings' => []];
    }
    return $values;
  }

}

我们将扩展基础设置类 EptSettingsDefaultWidget。在注解注释 @FieldWidget 中,我们将把小部件命名为 id = "ept_settings_simple",并设置 label = @Translation("EPT Simple settings")

/**
 * Plugin implementation of the 'ept_settings_simple' widget.
 *
 * @FieldWidget(
 *   id = "ept_settings_simple",
 *   label = @Translation("EPT simple paragraph settings"),
 *   field_types = {
 *     "ept_settings"
 *   }
 * )
 */

我们还实现了两个方法:formElement()massageFormValues()。你可以保持 massageFormValues() 原样。Drupal 会自动将所有设置序列化到一个字段 field_ept_settings 中。因此无论你有多少设置,它们都会以序列化数组的形式存储,你只需要使用 Form API 指定设置字段即可:

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

formElement() 中,我们将定义设置字段。让我们隐藏 DOM 盒和边框设置:

  /**
   * {@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['ept_settings']['design_options']['box1']);
    unset($element['ept_settings']['design_options']['other_settings']['border_color']);
    unset($element['ept_settings']['design_options']['other_settings']['border_style']);
    unset($element['ept_settings']['design_options']['other_settings']['border_radius']);

    return $element;
  }

如果你为某个 EPT 段落类型应用了新的字段小部件:

简单 EPT 小部件
Simple EPT widget

你将会看到更精简的设置表单:

EPT 设置表单
EPT settings form

现在我们也会移除背景设置。如果你需要背景设置但不需要其他所有设置,你可以扩展 EptSettingsDefaultWidget 类并从它创建你自己的字段小部件。下面示例展示了如何让 EPT Settings 尽可能小:

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

我们的表单现在已经只剩下两个设置:

仅两个字段
Only two fields

接下来只需添加用于底部外边距的 Spacing(间距)字段。我们将使用附加类和 CSS 来组织间距:

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

也许你需要更大的间距列表,欢迎扩展 EptSettingsSimpleWidget 类,并像我们对 EptSettingsDefaultWidget 类所做的那样,从它创建你自己的字段小部件类。

$element['ept_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]->ept_settings['design_options']['other_settings']['spacing'] ?? 'spacing-none',
    ];

现在我想到三种(实则列了四种)为我们的区块添加样式的方法:

1. 覆盖区块模板,并在其中将 spacing 作为区块类设置。

2. 动态生成样式,并将其作为每个段落的自定义 CSS 样式引入。

3. 通过为每个 EPT 段落生成自定义 JavaScript,用 JavaScript 添加类。

4. 在 template_preprocess_block() 函数中覆盖类列表。

以上方法都可行,但我认为使用 template_process_paragraph() 函数会更容易。至少我们已经在 ebt_core.module 文件中有了 ept_core_preprocess_block() 函数。让我们来用它:

...
  if (!empty($ept_settings[0]['ept_settings']['design_options']['other_settings']['spacing'])) {
    $variables['attributes']['class'][] = $ept_settings[0]['ept_settings']['design_options']['other_settings']['spacing'];
  }
...
中等间距
Medium spacing
间距类
Spacing class

现在我们将 Spacing 字段的键作为类名传递,并使用 CSS 基于这些类来定义外边距的数值:

/ebt_core/scss/ept_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;
}

你可以在自定义 CSS 文件中覆盖这些数值,例如通过使用内容或 body 标签上的任意类:

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

你也可以在自定义的 EBT 设置字段小部件类中覆盖间距列表。

就这样,现在你可以在为 EBT 区块设置外边距时,选择使用 DOM Box 或者简单的下拉选择框。

欢迎就 EBT 模块在 Drupal.org 上提问或通过联系表单联系我:

联系

在 Drupal.org 上创建一个 issue

在 LinkedIn 上保持联系