1

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?

2 Answers 2

1

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.

1
  • 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.
    – Anders
    May 30, 2023 at 16:56
0

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.