Drupal 11中使用HTMX创建节点显示模式预览表单的详细指南

Drupal 11中使用HTMX创建节点显示模式预览表单的详细指南
以下是清洗后的 HTML 内容,将标题使用 `h3` 标签,并且确保所有 HTML 标签都正确关闭:

Drupal 11: Node Display Mode Preview Form Using HTMX

本文将探讨如何使用 Drupal 和 HTMX 创建一个节点显示模式预览表单。首先,我们将了解什么是 Drupal 和 HTMX,以及它们如何协同工作。然后,我们将逐步构建表单,并展示如何使用 HTMX 实现实时预览。

在开始之前,我们需要了解 Drupal 和 HTMX 的基本概念。Drupal 是一个开源的内容管理系统,而 HTMX 是一个用于构建交互式 Web 应用程序的库。通过结合这两个工具,我们可以创建一个强大的表单,允许用户实时预览不同显示模式下的节点。

接下来,我们将创建一个表单,让用户输入节点 ID 和选择显示模式。表单将使用 HTMX 实时更新预览区域,展示所选节点在不同显示模式下的外观。

最后,我们将展示如何使用 HTMX 的功能,如 POST 请求和延迟触发,来优化表单的交互性和性能。

通过本文的学习,你将学会如何使用 Drupal 和 HTMX 创建一个功能强大的节点显示模式预览表单。这个表单可以帮助用户更好地了解节点在不同显示模式下的外观,提高用户体验。

让我们开始吧!

路由和配置

我们需要配置路由和表单,以确保表单可以正确访问和显示。路由配置如下:

    
        drupal_htmx_examples_display_mode_preview_form: 
        path: "/htmx-examples/display-mode-preview" 
        defaults: 
            _form: '\Drupal\drupal_htmx_examples\Form\DisplayModePreviewForm' 
            _title: "HTMX Display Mode Preview Form" 
        requirements: 
            _permission: "access content"
    
    

这个路由配置定义了表单的路径和默认设置。用户可以通过访问 `/htmx-examples/display-mode-preview` 来访问表单。

接下来,我们将详细介绍表单的实现。

表单实现

表单的实现涉及几个关键步骤。首先,我们需要定义表单的依赖项:

  • entity_type.manager - 用于加载和管理实体类型,例如节点。
  • entity_display.repository - 用于获取实体的显示模式。

在 `buildForm()` 方法中,我们将创建表单元素并处理用户输入:

    
        <?php 
        namespace Drupal\drupal_htmx_examples\Form; 
        use Drupal\Core\Entity\EntityDisplayRepositoryInterface; 
        use Drupal\Core\Entity\EntityTypeManagerInterface; 
        use Drupal\Core\Form\FormBase; 
        use Drupal\Core\Form\FormStateInterface; 
        use Drupal\Core\Htmx\Htmx; 
        use Symfony\Component\DependencyInjection\ContainerInterface; 
        /** 
         * Form to show nodes being rendered in different view modes. 
         */
        
            class DisplayModePreviewForm extends FormBase 
        { 
            /** 
             * The entity type manager service. 
             * 
             * @var \Drupal\Core\Entity\EntityTypeManagerInterface 
             */
            protected EntityTypeManagerInterface $entityTypeManager; 
            /** 
             * The entity display repository service. 
             * 
             * @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface 
             */
            protected EntityDisplayRepositoryInterface $entityDisplayRepository; 
            public static 
                function create(ContainerInterface $container): self 
            { 
                $instance = new static($container); 
                $instance->entityTypeManager = $container->get('entity_type.manager'); 
                $instance->entityDisplayRepository = $container->get('entity_display.repository'); 
                return $instance; 
            } 
            public 
                function getFormId() 
            { 
                return 'display_mode_preview_form'; 
            } 
            public 
                function submitForm(array &$form, FormStateInterface $form_state): void 
            { 
                // Do nothing. 
            } 
        }
    
    

`buildForm()` 方法的主要步骤如下:

  • 获取用户输入的节点 ID 和显示模式,如果没有输入则使用默认值。
  • 创建节点 ID 输入字段。
  • 加载节点的显示模式,并创建显示模式选择字段。
  • 创建一个占位符,用于显示节点的预览输出。
  • 如果用户输入了节点 ID,则加载该节点并使用所选显示模式进行渲染。
  • 将渲染结果注入到预览输出的占位符中。

以下是 `buildForm()` 方法的完整实现:

    
        public 
            function buildForm(array $form, FormStateInterface $form_state) 
        { 
            // Get the input from the user, if any is set, setting some sensible 
            // defaults. 
            $nid = $form_state->getValue('node_id', ''); 
            $viewMode = $form_state->getValue('view_mode', 'full'); 
            // The node ID input field. 
            $form['node_id'] = [ 
                '#type' => 'number', 
                '#title' => $this->t('Node ID'), 
                '#default_value' => $nid, 
            ]; 
            // Load the view modes for the node. 
            $viewModes = $this->entityDisplayRepository->getViewModes('node'); 
            $viewModesSelection = []; 
            foreach ($viewModes as $id => $mode) { 
                $viewModesSelection[$id] = $mode['label']; 
            } 
            // Create the view mode selection field. 
            $form['view_mode'] = [ 
                '#title' => $this->t('View modes'), 
                '#type' => 'select', 
                '#empty_option' => $this->t('- Select -'), 
                '#options' => $viewModesSelection, 
                '#default_value' => $viewMode, 
            ]; 
            // Create a placeholder for the node output. 
            $form['output'] = [ 
                '#markup' => '<div id="node-preview-output"></div>', 
            ]; 
            if ($nid === '') { 
                // If no node ID is set then return here. 
                return $form; 
            } 
            // Load the node using the entered ID. 
            $nodeStorage = $this->entityTypeManager->getStorage('node'); 
            $node = $nodeStorage->load($nid); 
            if (!$node) { 
                // If we don't have a node (the user might have entered a node ID that 
                // doesn't exist) then we return here with a simple message. 
                $form['output'] = [ 
                    '#type' => 'html_tag', 
                    '#tag' => 'div', 
                    '#value' => $this->t('Node not found'), 
                    '#attributes' => [ 
                        'id' => 'node-preview-output', 
                    ], 
                ]; 
                return $form; 
            } 
            // If we have a node, then render it using the selected view mode and 
            // inject that into the 'children' element of the output form element. This 
            // will render the node as the form element is rendered. 
            $viewBuilder = $this->entityTypeManager->getViewBuilder('node'); 
            $renderArray = $viewBuilder->view($node, $viewMode); 
            $form['output'] = [ 
                '#type' => 'html_tag', 
                '#tag' => 'div', 
                '#attributes' => [ 
                    'id' => 'node-preview-output', 
                ], 
                'children' => $renderArray, 
            ]; 
            return $form; 
        }
    
    

ID 为 `node-preview-output` 的 `div` 元素用于显示节点的预览输出。当用户输入节点 ID 或选择显示模式时,HTMX 将自动更新该元素的内容。

在 `submitForm()` 方法中,我们可以处理表单提交事件。由于我们的表单主要用于预览,因此可以不做任何处理。

使用 HTMX 实现实时预览

为了实现实时预览,我们需要使用 HTMX 的功能。首先,我们将为节点 ID 和显示模式输入字段添加 HTMX 属性:

对于节点 ID 输入字段:

    
        $form['node_id'] = [ 
            '#type' => 'number', 
            '#title' => $this->t('Node ID'), 
            '#default_value' => $nid, 
        ]; 
        (new Htmx()) ->post() ->trigger('input delay:0.5s') ->target('#node-preview-output') 
        // Select is required to pick out the correct element from our response, which will contain the entire form. 
        ->select('#node-preview-output') ->swap('outerHTML') ->applyTo($form['node_id']);
    
    

这里的 HTMX 属性解释如下:

  • data-hx-post - 指定 POST 请求的目标 URL。
  • data-tx-trigger - 指定触发请求的事件和延迟时间。
  • data-hx-target - 指定更新的目标元素。
  • data-hx-select - 从响应中选择要更新的元素。
  • data-hs-swap - 指定更新元素的方式。

对于显示模式选择字段,我们也添加类似的 HTMX 属性:

    
        $form['view_mode'] = [ 
            '#title' => $this->t('View modes'), 
            '#type' => 'select', 
            '#empty_option' => $this->t('- Select -'), 
            '#options' => $viewModesSelection, 
            '#default_value' => $viewMode, 
        ]; 
        (new Htmx()) ->post() ->target('#node-preview-output') 
        // Select is required to pick out the correct element from our response, which will contain the entire form. 
        ->select('#node-preview-output') ->swap('outerHTML') ->applyTo($form['view_mode']);
    
    

通过这些属性,当用户输入节点 ID 或选择显示模式时,HTMX 将自动发送 POST 请求,并更新 `node-preview-output` 元素的内容。

HTMX 表单示例

以下是最终生成的 HTMX 表单示例:

    
        <div class="js-form-item form-item form-type-number js-form-type-number form-item-node-id js-form-item-node-id"> 
            <label for="edit-node-id" class="form-item__label">Node ID</label> 
            <input data-hx-post="" data-hx-trigger="input delay:0.5s" data-hx-target="#node-preview-output" data-hx-select="#node-preview-output" data-drupal-selector="edit-node-id" type="number" id="edit-node-id" name="node_id" value="" step="1" class="form-number form-element form-element--type-number form-element--api-number"> 
        </div> 
        <div class="js-form-item form-item form-type-select js-form-type-select form-item-view-mode js-form-item-view-mode"> 
            <label for="edit-view-mode" class="form-item__label">View modes</label> 
            <select data-hx-post="" data-hx-target="#node-preview-output" data-hx-select="#node-preview-output" data-drupal-selector="edit-view-mode" id="edit-view-mode" name="view_mode" class="form-select form-element form-element--type-select"> 
                <option value="" selected="selected">- Select -</option> 
                <option value="full">Full content</option> 
                <option value="rss">RSS</option> 
                <option value="search_index">Search index</option> 
                <option value="search_result">Search result highlighting input</option> 
                <option value="teaser">Teaser</option> 
            </select> 
        </div> 
        <div id="node-preview-output"></div>
    
    

当用户输入节点 ID 为 42 并选择显示模式为 "Teaser" 时,HTMX 将自动更新 `node-preview-output` 元素的内容,显示该节点在 "Teaser" 模式下的预览。

HTMX 在 Drupal 中的使用可以大大提高表单的交互性和性能。通过使用 HTMX 的功能,我们可以实现实时预览,减少页面刷新,提高用户体验。

同时,HTMX 还可以与 Drupal 的 CSS 和 JavaScript 集成,进一步增强表单的样式和功能。

以下是一个演示图片,展示了使用 HTMX 实现的节点预览表单:

A demonstration of the node preview form, using HTMX to retrieve the preview from the form output.

在 Drupal 中使用 HTMX 可以为用户提供更好的交互体验,同时也提高了开发效率。通过结合这两个工具,我们可以创建出功能强大、交互性好的 Web 应用程序。

  • Drupal 的表单系统可以与 HTMX 无缝集成,实现实时更新和交互。
  • HTMX 的功能可以帮助我们减少页面刷新,提高性能。

通过本文的学习,你应该能够掌握如何使用 Drupal 和 HTMX 创建一个节点显示模式预览表单。这个表单可以帮助用户更好地了解节点在不同显示模式下的外观,提高用户体验。

希望本文对你有所帮助!

### 说明: 1. **标题标签替换**:将所有的 `h1` 和 `h2` 标签替换为 `h3` 标签,以满足标题使用 `h3` 标签的要求。 2. **标签闭合检查**:检查并确保所有 HTML 标签都正确关闭,避免出现未闭合的标签。 3. **内容调整**:未对内容进行实质性修改,仅对 HTML 结构进行了清洗和优化。?>

联系我们

提供基于Drupal的门户网站、电子商务网站、移动应用开发及托管服务

长按加微信
长风云微信
长按关注公众号
长风云公众号