Skip to main content
Category:

How to create dynamic layouts using derivatives in Drupal 8 & 9

 

if you wanted to create a flexible layout builder, you'd give the site administrator some user interface to declare a new layout, and the configuration for each layout would be saved as a config entity. Then you'd register a layout class that used a "deriver" to dynamically register a layout plugin for each of those saved config entities.

Article how to create custom configuration entity type

So, first you'd register the layout class, for example:

<?php

namespace Drupal\mymodule\Plugin\Layout;

use Drupal\Core\Layout\LayoutDefault;

/**
 * A layout from our flexible layout builder.
 *
 * @Layout(
 *   id = "flexible_layout",
 *   deriver = "Drupal\mymodule\Plugin\Deriver\FlexibleLayoutDeriver",
 *   admin_label = @Translation("Flexible layout"),
 *   category = @Translation("Flexible layout category"),
 * )
 */
class FlexibleLayout extends LayoutDefault {

  /**
   * {@inheritdoc}
   */
  public function build(array $regions) {
    $render_array = parent::build($regions);
    // Since this is a flexible layout builder, you probably need to do
    // something special to render the layout, so we override the ::build()
    // method which is responsible for creating a render array.
    return $render_array;
  }

}

 

Now, here is what an example deriver could look like:

 

namespace Drupal\mymodule\Plugin\Deriver;

use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\mymodule\Plugin\Layout\FlexibleLayout;
use Drupal\Core\Layout\LayoutDefinition;

/**
 * Makes a flexible layout for each layout config entity.
 */
class FlexibleLayoutDeriver extends DeriverBase {

  /**
   * {@inheritdoc}
   */
  public function getDerivativeDefinitions($base_plugin_definition) {
    // Here we need to magically get a list of the config entities.
    // I leave this as an exercise for the reader. :-)
    $config_entities = [];

    // Now we loop over them and declare the derivatives.
    foreach ($config_entities as $entity) {
      // Here we fill in any missing keys on the layout annotation.
      $this->derivatives[$entity->id()] = new LayoutDefinition([
        'class' => FlexibleLayout::class,
        'label' => $entity->label(),
        'category' => $entity->getCategory(),
        'regions' => $entity->getRegions(),
      ]);
    }

    return $this->derivatives;
  }

}

 

Other example how deriver could look like:

 

<?php

namespace Drupal\mymodule\Plugin\Deriver;

use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\mymodule\Plugin\Layout\FlexibleLayout;
use Drupal\Core\Layout\LayoutDefinition;

/**
 * Makes a flexible layout for each layout config entity.
 */
class FlexibleLayoutDeriver extends DeriverBase
{

  /**
   * {@inheritdoc}
   */
  public function getDerivativeDefinitions($base_plugin_definition)
  {

    for ($i = 0; $i < 3; $i++) {
      $this->derivatives["flexible_layout" . $i] = new LayoutDefinition([
        'class' => FlexibleLayout::class,
        'label' => "flexible layout " . $i,
        'category' => "Custom",
        'regions' => ['main' => ['label' => 'Main content']],
        'template' => 'flexible-layout-' . $i,
        'path' => drupal_get_path('module', 'mymodule') . "/layouts/flexible-layout",
      ]);
    }

    return $this->derivatives;
  }

}

 

Our custom layouts are like this:

flexible layouts

 

Useful links:

https://www.drupal.org/docs/drupal-apis/layout-api/how-to-register-layouts#using-derivatives

how to create custom configuration entity type

Riadh Rahmi

Senior Web Developer PHP/Drupal & Laravel

I am a senior web developer, I have experience in planning and developing large scale dynamic web solutions especially in Drupal & Laravel.

Web Posts

Search

Page Facebook