Score:1

How to pass node argument to a local task form?

bo flag

Suppose I have a route for a local task like this:

MODULE_NAME.node_options:
  path: '/node/{node}/options'
  defaults:
    _form: '\Drupal\MODULE_NAME\Form\NodeOptionsForm'
    _title: 'Options'
  requirements:
    _entity_access: 'node.update'
    node: \d+
  options:
    parameters:
      node:
        type: 'entity:node'

NodeOptionsForm shall present 2-3 radio buttons to the user to select a service to perform on the node, e.g. create a summary of the body using A.I.

a) Which base class should I use for the form?

b) How is the {node} argument actually passed to the form instance? Or in other words, how must the form instance be created in order to have access to the node?

Score:1
ge flag

You can use the NodeInterface class in your buildForm like below

<?php

namespace Drupal\MODULE_NAME\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\node\NodeInterface;

/**
 * @internal
 */
class NodeOptionsForm extends FormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'make_special_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, NodeInterface $node = NULL) {
    // Node object will be in $node and you can perform your logic in this function.
    $form['#title'] = $node->label();
    $form['#node'] = $node;
    return $form;
  }

a) Which base class should I use for the form? => FormBase class will be used for all basic forms unless it a config form.

b) How is the {node} argument actually passed to the form instance? Or in other words, how must the form instance be created in order to have access to the node? => You can pass it as NodeInterface $node in buildForm.

Anders avatar
bo flag
Thank you so much. This isn't obvious until you learn about it from an example. The Drupal documentation is a bit challenging, if you come from different languages that use Doxygen, for example.
Score:0
us flag

Routes for local tasks do not have different requirements, compared to routes that are not used for local tasks, apart from being added in the .links.task.yml file for the module.

For example, the Book module define the following local task.

entity.node.book_outline_form:
  route_name: entity.node.book_outline_form
  base_route: entity.node.canonical
  title: Outline
  weight: 2

The route is defined by these lines.

entity.node.book_outline_form:
  path: '/node/{node}/outline'
  defaults:
    _entity_form: 'node.book_outline'
    _title: 'Outline'
  requirements:
    _permission: 'administer book outlines'
    _entity_access: 'node.view'
    node: \d+
  options:
    _node_operation_route: TRUE

In this case, the form is defined with _entity_form. It could have used _form too; in that case, the _form value is the name (namespace included) of a class that implements FormInterface, which is implemented by the FormBase, a base class module can extend for their forms.
Other base classes that can be used for forms are ConfigFormBase, for configuration forms, ConfirmFormBase, for confirmation forms, or ImageEffectFormBase, for an image effect settings.

Any route parameters are passed to the buildForm() method any class that implements FormInterface needs to implement.

The alternative is doing like the Book module does, adding a new form class using hook_entity_build() and using _entity_form in the route definition.

function book_entity_type_build(array &$entity_types) {
  /** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */
  $entity_types['node']->setFormClass('book_outline', 'Drupal\\book\\Form\\BookOutlineForm')
    ->setLinkTemplate('book-outline-form', '/node/{node}/outline')
    ->setLinkTemplate('book-remove-form', '/node/{node}/outline/remove')
    ->addConstraint('BookOutline', []);
}

In this case, the edited entity is passed in $this->entity to the methods of the entity form class.

I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.