Do you want to know how to Drupal?

Let's Drupal

How to add local tasks dynamically in Drupal 8?

In some cases we want to generate local task based on some data. In our example we want to provide custom settings per node type for it we will provide local tasks based on node types. 

As usual full example you can find here: https://github.com/LOBsTerr/drupal-modules-examples

First we need to define deriver plugin, which will expose the local tasks dynamically for us.

We will setup a route, which will accept a parameter "type" and we will just print it in order to see that it is a different page.

local_tasks.dynamic_tasks:
  path: '/dynamic-tasks/{type}'
  defaults:
    _controller: '\Drupal\local_tasks\Controller\LocalTasksController::dynamicTasks'
    _title: 'Dynamic tasks'
    type: ''
  requirements:
    _permission: 'access content'

and controller method

public function dynamicTasks($type = NULL) {
    return [
      '#markup' => $this->t('This is an example : @type', [
        '@type' => $type
      ]),
    ];
  }

Then we add in your file [your_module_name].links.task.yml (in our case local_tasks.links.task.yml), we set a deriver class

# Dynamically add local tasks.
local_tasks.dynamic_tasks:
  route_name: 'local_tasks.dynamic_tasks'
  title: 'Dynamic tasks'
  base_route: 'local_tasks.dynamic_tasks'
  deriver: Drupal\local_tasks\Plugin\Derivative\NodeTypeLocalTask # We set derive class, which will provide local tasks dynamically.

 

Now we can add a class Drupal\local_tasks\Plugin\Derivative\NodeTypeLocalTask.php

<?php

namespace Drupal\local_tasks\Plugin\Derivative;

use Drupal\Component\Plugin\Derivative\DeriverBase;

/**
 * Provides dynamic tabs based on node types.
 */
class NodeTypeLocalTask extends DeriverBase {

  /**
   * {@inheritdoc}
   */
  public function getDerivativeDefinitions($base_plugin_definition) {
    // Get node types.
    $node_types = \Drupal::entityTypeManager()
      ->getStorage('node_type')
      ->loadMultiple();

    foreach ($node_types as $node_type_name => $node_type) {
      $this->derivatives[$node_type_name] = $base_plugin_definition;
      $this->derivatives[$node_type_name]['title'] = $node_type->label();
      $this->derivatives[$node_type_name]['route_parameters'] = ['type' => $node_type_name];
    }

    return $this->derivatives;
  }

}

 

As you can see above, we get list of node types and pass title and route parameters. The route name comes from local_tasks.links.task.yml

The only thin left is to clean the cache and open /dynamic-tasks/, you should see the list of node types as tabs.

Like this you can easily add local tasks dynamically on your custom page applying more complicated logic in Drupal.