Two useful approaches are outlined in the Drupal 8 guide / Providing module defined actions. These are:
- Derivers that dynamically generate one or multiple actions
- Custom classes for the actions
I nearly solved the issue with approach 1. However, I'm still struggling with caching. This is my solution so far:
namespace Drupal\mymodule\Plugin\Derivative;
use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\mymodule\Entity\ItemInterface;
use Drupal\mymodule\Entity\Item;
/**
* Defines dynamic actions.
*/
class ItemLocalActions extends DeriverBase {
/**
* {@inheritdoc}
*/
public function getDerivativeDefinitions($base_plugin_definition) {
// Implement dynamic logic to provide values for the same keys as in example.links.task.yml.
$id = \Drupal::routeMatch()->getRawParameter('item');
$item = Item::load($id);
if ($item instanceof ItemInterface) {
switch($item->getStatus()) {
case ItemInterface::STATUS_NEW:
$this->derivatives['entity.item.action'] = $base_plugin_definition;
$this->derivatives['entity.item.action']['title'] = t('Do something');
$this->derivatives['entity.item.action']['route_name'] = 'entity.item.action';
break;
// add more derivative definitions here, depending on the item's state
}
}
return $this->derivatives;
}
}
and in mymodule.links.action.yml:
entity.item.state_actions:
deriver: '\Drupal\mymodule\Plugin\Derivative\ItemLocalActions'
cache_tags:
- item_list
appears_on:
- entity.item.canonical
As stated above, caching is still a problem. Even though I set the appropriate cache tags, the actions are still rendered from cache.
Related questions: