How to create custom contextual links programmatically in drupal 8 & 9
Contextual links are defined in a YAML format, named after the module they are defined by. Such as block.links.contextual.yml
for this example from block module:
block_configure:
title: 'Configure block'
route_name: 'block.admin_edit'
group: 'block'
Rendering contextual links
The contextual link rendering process takes the groups from the #contextual_links
keys in the render array. For example the BlockViewBuilder provides this contextual links list:
public function viewMultiple(array $entities = array(), $view_mode = 'full', $langcode = NULL) {
$build = array();
foreach ($entities as $key => $entity) {
// ...
$build[$entity_id] = [
'#theme' => 'block',
// ...
'#contextual_links' => [
'block' => [
'route_parameters' => ['block' => $entity->id()],
],
],
// ...
];
}
// ...
}
The 'block'
key in the #contextual_links render array establishes the 'block'
group. All links belonging to the 'block'
group will be displayed as contextual links. The value provided for the key is an array with route parameters to be able to convert routes related to this block to paths for the links (with the assumption that routes used as contextual links on blocks will include the block identifier as a dynamic component). Only routes which can be fully resolved to a path with route parameters should be added to a group.
For example the block.admin_edit
route that is referenced in the contextual link above is defined as follows (in block.routing.yml
):
block.admin_edit:
path: '/admin/structure/block/manage/{block}'
defaults:
_entity_form: 'block.default'
_title: 'Configure block'
requirements:
_entity_access: 'block.update'
The 'block'
route parameter defined in the #contextual_links
array allows the system to resolve this to the proper path to the block edit page by replacing {block}
with the provided parameter, the block id.
Contextual links are stored in title_suffix. This variable needs to be printed in the html.twig file, such as in this example from block.links.contextual.yml
.
<div{{ attributes }}>
{{ title_suffix }}
...
</div>
Example how to customize contextual link behaviour
The default contextual links implementation is in ContextualLinkDefault. You can extend this class and modify the behaviour of a desired contextual link by providing the class on the definition.
Such as to use a dynamic title for a contextual link, you can extend the class, override the getTitle()
method and provide the class in the definition:
example.customtitle:
title: 'Custom title example'
route_name: 'example.admin_edit'
group: 'example'
class: '\Drupal\example\Plugin\Menu\ContextualLink\CustomContextualLink'