Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save paullinney/f956155d862965f11c323ec6c94578ad to your computer and use it in GitHub Desktop.

Select an option

Save paullinney/f956155d862965f11c323ec6c94578ad to your computer and use it in GitHub Desktop.
Drupal Block to Single Directory Components Pattern

Drupal Block to Single Directory Components Pattern

Alias: "Block-SDC"

Drupal Block Component

%%{init: {'theme': 'dark', 'textColor': 'white' } }%%
sequenceDiagram
  Block->>Block: Generate build render array
  Block->>Theme: Theme file
  Theme->>Theme: `templates/sdc_block.twig.html`
  Theme->>SDC: Include Single Directory Component
  SDC->>SDC: `sdc-my-component`
Loading

Block

Plugin

src/Plugin/Block/MyComponentSdcBlock.php

<?php

declare(strict_types=1);

namespace Drupal\my_components\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides an SDC block.
 *
 * @Block(
 *   id = "my_components_sdc_block",
 *   admin_label = @Translation("SDC Block"),
 *   category = @Translation("My Component"),
 * )
 */
final class MyComponentSdcBlock extends BlockBase implements ContainerFactoryPluginInterface {

  /**
   * @param array $configuration
   * @param string $plugin_id
   * @param mixed $plugin_definition
   * @param CacheBackendInterface $cacheBackend
   * @param TimeInterface $datetime
   */
  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    private readonly TimeInterface $datetime
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
  }

  /**
   * @param ContainerInterface $container
   * @param array $configuration
   * @param string $plugin_id
   * @param mixed $plugin_definition
   *
   * @return static
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('datetime.time')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function build(): array {

    $data = [
      'text' => 'Block SDC',
      'subtitle' => 'My Text',
      'requested' => $this->datetime->getRequestTime()
    ];

    $build['content'] = [
      '#theme' => 'sdc_block',
      '#data' => $data,
    ];
    return $build;
  }

}

Template

templates/sdc_block.twig.html

{{
  include('my_components:sdc-my-component', {
    text: content.data.text,
    subtitle: content.data.subtitle,
    requested: content.data.requested,
  },
  with_context = false)
}}

Single Directory Component

Module Structure

Components to be place inside a module or theme within a components directory.

.my_components
│
├── src
│   └── Plugin
│       └── Block
│           └── MyComponentSdcBlock.php
├── assets
│   └── css
│       └── component.css
├── components
│   └── sdc-my-component
│       ├── sdc-my-component.component.yml
│       ├── sdc-my-component.css
│       ├── sdc-my-component.js
│       ├── sdc-my-component.twig
│       └── README.md
├── my_components.info.yml
├── my_components.module
├── my_components.services.yml
├── src
└── templates

Component Structure

sdc-my-component
  ├── sdc-my-component.component.yml
  ├── sdc-my-component.css
  ├── sdc-my-component.js
  ├── sdc-my-component.twig

Note: CSS and JS files are optional and loaded only if present.

Files


File: sdc-my-component.component.yml

'$schema': 'https://git.drupalcode.org/project/drupal/-/raw/10.1.x/core/modules/sdc/src/metadata.schema.json'
name: My Component
status: stable
props:
  type: object
  properties:
    text:
      title: Text
      type: string
    subtitle:
      title: Sub Title
      type: string
      title: Requested
      type: string

File: sdc-my-component.twig

<sdc-my-component class="composition-vertical">
  <div class="headline">
    {{ text }}
    {% if subtitle | length %}
      <h3>{{ subtitle }}</h3>
    {% endif %}
    <p>{{ requested }}</p>
  </div>
 </sdc-my-component>

File: sdc-my-component.js (optional)

(function(Drupal) {

  Drupal.behaviors.sdcMyComponent = {
    attach(context) {
      console.log('@todo My Component.');
    },
  };

})(Drupal);

File: sdc-my-component.css (optional)

@import url("../../assets/css/component.css");

.headline {
    color: green;
    margin: 1em 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment