Drupal 9:在节点编辑页面上自动注入段落形式

前几天,我试图做一些我认为很简单的事情,但事实证明,要想真正做到这一点真的很困难。我有一个安装了Paragraphs的Drupal 9网站,我希望用户单击节点编辑表单上的按钮,然后将一个特定的Paragraph注入到Paragraph字段中。

我找到了解决此问题的2种解决方案,它们以略有不同的方式解决了该问题。

ggy回现有事件

在最初尝试使此方法生效之后,我决定使用背负式方法。这实质上是在侦听用户交互,然后触发将段落插入字段中的“段落添加”事件。我正在听的用户交互是用户在选择列表中选择不同的元素。

为了使此工作正常进行,我在页面上添加了一些JavaScript,并将其附加到名为“ field_type”的选择列表字段中。

function my_module_form_node_page_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state)

{

  $form['field_type']['widget']['#attached']['library'][] = 'my_module/node';

}

node:

  js:

    js/piggy-back.js: {}

  dependencies:

    - core/drupal

这将加载到名为piggy-back.js的JavaScript文件中。

如下所示,该文件用于将附加到不同“段落”添加按钮的不同事件汇总在一起。当用户更改字段类型选择列表时,将触发一个事件,然后触发一个段落事件。

(function ($, Drupal, drupalSettings) {

 

  'use strict';

 

  Drupal.behaviors.bform = {

    attach : function(context, settings) {

      // 加载现有的更改事件。

      var paragraphDetailEvents = $._data($("#field-paragraph-detail-add-more")[0], "events");

      var paragraphHeaderEvents = $._data($("#field-paragraph-header-add-more")[0], "events");

 

      $('#edit-field-type').change(function(event) {

        let changeValue = $(this).val();

        if (changeValue == 1) {

          $.each(paragraphDetailEvents.mousedown, function () {

            this.handler(event);

          });

        }

        if (changeValue == 2) {

          $.each(paragraphHeaderEvents.mousedown, function () {

            this.handler(event);

          });

        }

      });

    }

  };

 

})(jQuery, Drupal);

您可能可以修改此代码以适合您的需求,但这是对实际产生预期结果的问题的简单解决方案。

注入段落按钮Ajax回调

尽管搭载方法有效,但我真正想做的是完全控制ajax流和所得到的响应。浏览“段落”模块使我想到了各种不同的代码,这些代码似乎并没有真正产生所需的结果。在运行了几次代码之后,我能够将所需的组件提取到单个模块中。

这里需要的第一件事是一个表单元素,以控制将Paragraph实体表单注入到页面中。这由提交按钮处理,该提交按钮使用hook_form_node_page_form_alter()挂钩插入到节点编辑表单中。该按钮被注入到名为“ field_type”的字段旁边,但是我已经对此进行了抽象,以便您可以将其移动到所需的任何位置。段落字段名称还需要在顶部抽象为一个变量,因此您可以将其指向所需的任何段落字段。对“添加更多”字段和类名称的引用将与Paragraph表单本身集成在一起。

    function my_module_form_node_page_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state)

    {

      $paragraphFieldName = 'field_paragraph';

      $injectParagraphFieldName = 'field_type';

     

      $paragraphField = NestedArray::getValue($form, [$paragraphFieldName]);

     

      $injectParagraphField = NestedArray::getValue($form, [$injectParagraphFieldName]);

     

      $injectParagraphField['inject_paragraph'] = [

        '#type' => 'submit',

        '#name' => 'field_type_my_module',

        '#value' => t('Inject Paragraph'),

        '#attributes' => ['class' => ['field-set-selection-submit']],

        '#limit_validation_errors' => [array_merge($paragraphField['#parents'], [$paragraphFieldName, 'add_more'])],

        '#submit' => [['\Drupal\my_module\InjectParagraph', 'addParagraphSubmit']],

        '#ajax' => [

          'callback' => ['\Drupal\my_module\InjectParagraph', 'addParagraphAjax'],

          'wrapper' => str_replace('_', '-', $paragraphFieldName) . '-add-more-wrapper',

          'effect' => 'fade',

          'progress' => [

            'type' => 'fullscreen',

          ]

        ],

      ];

      NestedArray::setValue($form, [$injectParagraphFieldName], $injectParagraphField);

    }

    该按钮将充当用户输入,并在元素周围包装Submit和ajax处理程序。为了使此提交按钮正常工作,需要三件事。

    1. 提交callack,在提交按钮后调用。在上面的字段中,已将其创建为静态方法,然后放入类中。

    2. 一个limit_validation_errors。顾名思义,这将限制表单将产生的验证错误的数量。在这种情况下,我们告诉Drupal仅验证段落字段中是否存在错误,并在表单的其余部分执行“部分提交”。

    3. 在提交处理程序之后,在提交按钮时调用的Ajax回调。同样,它已被抽象到一个单独的类中。

    包含addParagraphSubmit和addParagraphAjax处理程序的类是执行操作的地方。这是完整的课程,我添加了很多评论以显示正在发生的事情。

    <?php

     

    namespace Drupal\my_module;

     

    use Drupal\Component\Utility\NestedArray;

    use Drupal\Core\Field\FieldStorageDefinitionInterface;

    use Drupal\Core\Form\FormStateInterface;

    use Drupal\paragraphs\Plugin\Field\FieldWidget\ParagraphsWidget;

     

    class InjectParagraph {

     

      public static function addParagraphSubmit(array $form, FormStateInterface $form_state)

      {

        // 设置有问题的段落字段。

        $paragraphFieldName = 'field_paragraph';

     

        // 从表单中提取段落字段。

        $element = NestedArray::getValue($form, [$paragraphFieldName, 'widget']);

        $field_name = $element['#field_name'];

        $field_parents = $element['#field_parents'];

     

        // 获取窗口小部件状态。

        $widget_state = static::getWidgetState($field_parents, $field_name, $form_state);

     

        // 插入新段落并增加项目数。

        $widget_state['selected_bundle'][] = 'detail';

        $widget_state['items_count']++;

     

        // 更新小部件状态。

        static::setWidgetState($field_parents, $field_name, $form_state, $widget_state);

     

        // 重建表格。

        $form_state->setRebuild();

      }

     

      public static function addParagraphAjax(array $form, FormStateInterface $form_state)

      {

        // 设置有问题的段落字段。

        $paragraphFieldName = 'field_paragraph';

     

        // 从表单中提取段落字段。

        $element = NestedArray::getValue($form, [$paragraphFieldName, 'widget']);

     

        // 使用所需的Ajax格式更新字段。

        $delta = $element['#max_delta'];

        $element[$delta]['#prefix'] = '<div>' . (isset($element[$delta]['#prefix']) ? $element[$delta]['#prefix'] : '');

        $element[$delta]['#suffix'] = (isset($element[$delta]['#suffix']) ? $element[$delta]['#suffix'] : '') . '</div>';

     

        // 从段落模块中清除添加更多增量。

        NestedArray::setValue(

          $element,

          ['add_more', 'add_more_delta', '#value'],

          ''

        );

     

        // 返回段落元素。

        return $element;

      }

     

      public static function getWidgetState(array $parents, $field_name, FormStateInterface $form_state) {

        return NestedArray::getValue($form_state->getStorage(), array_merge(['field_storage', '#parents'], $parents, ['#fields', $field_name]));

      }

     

      public static function setWidgetState(array $parents, $field_name, FormStateInterface $form_state, array $field_state) {

        NestedArray::setValue($form_state->getStorage(), array_merge(['field_storage', '#parents'], $parents, ['#fields', $field_name]), $field_state);

      }

    }

    如果您熟悉“段落”模块,那么您会认出其中的一些代码,因为这些部分已从“段落”模块中获取。我需要复制和粘贴此处所需的一些代码,因为它们在Paragraph小部件中被设置为私有或受保护的方法,因此无法访问。我在这里省略了一些细节,因为代码只会将一种类型的Paragraph注入到表单中。但是,如果您要这样做的话,这应该是足够的信息,可以助您一臂之力。表单状态被传递给两个函数,因此您应该能够对其进行检查并查看已选择的内容,然后相应地修改代码。

    本质上,事件的顺序如下。

    1. 用户单击节点表单上的新“插入段落”按钮。

    2. 对Drupal进行了ajax调用。

    3. Drupal表单处理开始。

    4. 触发名为addParagraphSubmit的提交处理程序。在这一步中,我们使用具有“ selected_bundle”属性的占位符小部件为要添加到表单中的段落实体注入占位符。我们添加的段落实体称为“详细信息”。

    5. 调用内部的Paragraph渲染函数,然后使用空白的Paragraph实体表单填充表单元素。

    6. 触发了名为addParagraphAjax的ajax处理程序。在此步骤中,将显示空的Paragraph实体表单,只是将其包装在某些HTML中,以便该表单的行为与普通的Paragraph表单相同。

    如您所见,在这里既需要提交处理程序,也需要ajax处理程序,以便正确插入Paragraph实体表单。如果没有将提交处理程序称为ajax处理程序,则它什么也不会做。确保同时调用这两个处理程序,这取决于我们注入的表单元素中的limit_validation_errors设置。如果缺少此元素,则仅调用ajax处理程序,该过程太迟了,无法添加Paragraph实体。我以前没有使用过此设置,因此不确定它做了什么,因此我什至可以就此设置撰写一篇完全独立的文章,因为它极大地改变了ajax回调的工作方式。

    经过数小时的调试,实验和调整,以上所有代码均已组合在一起。希望对您有用。

    以上是 Drupal 9:在节点编辑页面上自动注入段落形式 的全部内容, 来源链接: utcz.com/z/350535.html

    回到顶部