Not sure if this is an issue or me being new to Drupal / creating a custom block through code and i'm just not doing it right, but i've made my first custom block through code and tried adding it to a layout and the contextual links didn't appear to configure / move / delete the block.

I've created 3 functions in my block class as per documentation that I found - blockForm for the different editable fields, blockSubmit for what configuration settings to save and build for what to render.

Having a look around, I managed to get the contextual links loading after a refresh by setting configuration values for delta and uuid from the form state and adding them as contextual links in the build function (after looking at https://www.drupal.org/project/drupal/issues/3023334#comment-form and https://www.drupal.org/project/drupal/issues/3003666 that was referenced in the previous issue, however trying to do getCurrentComponent in the blockSubmit function wasn't returning anything when saving it to a test variable and I had to follow the first issue and put in some getters to get the values saving).

The code for the 3 functions I mentioned is:

/**
 * {@inheritdoc}
 */
public function blockForm($form, FormStateInterface $form_state)
{
    $config = $this->getConfiguration();

    $form['title'] = [
        '#type'          => 'textfield',
        '#title'         => $this->t('Title'),
        '#default_value' => $config['title'] ?: '',
    ];

    $form['copy'] = [
        '#type'          => 'text_format',
        '#title'         => $this->t('Copy'),
        '#format'        => 'full_html',
        '#default_value' => $config['copy']['value'] ?: '',
    ];

    return $form;
}

/**
 * {@inheritdoc}
 */
public function blockSubmit($form, FormStateInterface $form_state)
{
    $formObject = $form_state->getFormObject();
    $this->setConfigurationValue('title', $form_state->getValue('title'));
    $this->setConfigurationValue('copy', $form_state->getValue('copy'));
    $this->setConfigurationValue('delta', $formObject->getDelta());
    $this->setConfigurationValue('uuid', $formObject->getUuid());
}

/**
 * @return array
 */
public function build()
{
    $config = $this->getConfiguration();
    $node = \Drupal::routeMatch()->getParameter('node');

    $data = [
        '#contextual_links' => [
            'layout_builder_block' => [
                'route_parameters' => [
                    'section_storage_type' => 'overrides',
                    'section_storage'      => 'node.' . $node->id(),
                    'delta'                => $config['delta'],
                    'region'               => 'main',
                    'uuid'                 => $config['uuid'],
                ],
                'metadata' => [
                    'operations' => 'move:update:remove',
                ],
            ],
        ],
        'title'    => $config['title'] ?: '',
        'copy'     => $config['copy']['value'] ?: '',
    ];

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

Hope someone can help and apologies if I've put this in the wrong forum - it's my first post here too.

Thanks in advance

Comments

BryanLund’s picture

I figured out that getting the node parameter from the URL didn't always work as it was different URLs depending on what was happening and the node parameter wasn't always available, so I had to create a different function to get the node ID depending on this which seems to have sorted it, though moving the blocks around through drag / drop doesn't seem to work now (though moving them through the contextual link move option does work). The function I did was:

<code>

public function getNodeId()
{
    $nodeId = \Drupal::routeMatch()->getRawParameter('node');

    if (empty($nodeId)) {
        $uri = \Drupal::request()->getRequestUri();
        $uriParts = explode('/', $uri);

        if ($uriParts[1] === 'node') {
            $nodeId = $uriParts[2];
        } elseif ($uriParts[1] === 'layout_builder' && !empty($uriParts[5])) {
            $node = $uriParts[5];
            $nodeParts = explode('.', $node);
            $nodeId = $nodeParts[1];
        }
    }

    return (int)$nodeId;
}</code>