How to make a title block with a custom background

How to make a title block with a custom background

drupal

A common request I’ve received lately when building sites in Drupal is to make the background of the page title configurable to allow the user upload and change it.

image

Of course, this could be solved with a new block type with two fields, one for the image and one for the title. But then we would need to add the block for each page where we want to show the title.

How does Drupal handle page titles? Looking in the block admin page, I found that actually it is a block. Well, we need the same functionality of that block in our new one.

So looking for the class that contains the block machine name page_title_block I found Drupal\Core\Block\Plugin\Block\PageTitleBlock which implements TitleBlockPluginInterface. This is all the interface:

php

interface TitleBlockPluginInterface extends BlockPluginInterface {

/**

- Sets the title.
*
- @param string|array $title
- The page title: either a string for plain titles or a render array for
- formatted titles.
*/
public function setTitle($title);

}


Searching what uses that interface, I found that `BlockPageVariant` uses it to assign it a title:

``` php
    foreach ($this->blockRepository->getVisibleBlocksPerRegion($cacheable_metadata_list) as $region => $blocks) {
          /** @var $blocks \Drupal\block\BlockInterface[] */
          foreach ($blocks as $key => $block) {
            $block_plugin = $block->getPlugin();
            if ($block_plugin instanceof MainContentBlockPluginInterface) {
              $block_plugin->setMainContent($this->mainContent);
              $main_content_block_displayed = TRUE;
            }
            elseif ($block_plugin instanceof TitleBlockPluginInterface) {
              $block_plugin->setTitle($this->title);
            }
      //...

This means that if I create a custom block that implements TitleBlockPluginInterface I will get the page title automatically (thanks to BlockPageVariant)? Apparently, yes.

Lets start writing the custom block extending PageTitleBlock to use the title field implementation:

php

/**

- @Block(
- id = "myimagetitleblock",
- admin
label = "Image title block"
- )
*/
class ImageTitleBlock extends PageTitleBlock {

/**

- The image field.
*
- @var mixed
*/
protected $image;

public function defaultConfiguration() {
return [
'image' => [
'value' => '',
],
'label_display' => FALSE,
] + parent::defaultConfiguration();
}

/**

- {@inheritdoc}
*/
public function build() {
$build = [];

if (isset($this->configuration['image'])
&& !empty($this->configuration['image'])) {

$imagefield = $this->configuration['image'];
$image
uri = File::load($image_field[0]);

$build['image'] = [
'uri' => ImageStyle::load('titlebar')->buildUrl($imageuri->getFileUri()),
];
} else {
$build['image']['#markup'] = '[' . t('Picture') . ']';
}

return $build + parent::build();
}

/**

- {@inheritdoc}
*/
public function blockForm($form, FormStateInterface $form_state) {

$form['image'] = array(
'#type' => 'managedfile',
'#upload
location' => 'public://images/',
'#title' => $this->t('Image'),
'#description' => $this->t("Background image"),
'#defaultvalue' => $this->configuration['image'],
'#upload
validators' => array(
'filevalidateextensions' => array('gif png jpg jpeg'),
'filevalidatesize' => array(25600000),
),
'#states' => array(
'visible' => array(
':input[name="image_type"]' => array('value' => t('Upload New Image')),
)
)
);

return $form;
}

public function validateConfigurationForm(array &$form, FormStateInterface $formstate) {
if (!$form
state->getValue('image')) {
$form_state->setError($form['image'], $this->t('Select an image'));
}
}

/**

- {@inheritdoc}
/
public function blockSubmit($form, FormStateInterface $form_state) {
/
Fetch the array of the file stored temporarily in database */
$image = $form_state->getValue('image');

$this->configuration['image'] = $image;

/* Load the object of the file by it's fid */
$file = \Drupal\file\Entity\File::load($image[0]);

/* Set the status flag permanent of the file object */
$file->setPermanent();

/* Save the file in database */
$file->save();
}
}


After clearing Drupal cache, you will find your new shiny block waiting for you in the _Add block_ list. The build method returns the processed image URL (using _title_bar_ style) instead of the render array for an image so we can use it later.

Lets create _title_bar_ image style and configure it accordingly (in my case, resize and crop to a predefined size will do).

![](https://i.snap.as/ewM5PVG.png)

Then, update your theme to make sure that image url shows in a `style` attribute, or a `data-*` if youre using javascript to load the image.

_blockimage-title-block.html.twig_

``` twig
    <div{{ attributes.setAttribute('style',
        'background: #787c8a url(' ~ content.image.uri ~ ') no-repeat center;') }}>
      {{ title_prefix }}
      {% if label %}
        <h2{{ title_attributes }}>{{ label }}</h2>
      {% endif %}
      {{ title_suffix }}
      {% block content %}
        {{ content }}
      {% endblock %}
    </div>
    ...

Lets test it!

image

image

image


You'll only receive email when they publish something new.

More from Arturo Linares
All posts