1

I have normal Drupal8 Content entity, and I'd like to set up some additional arguments for the entity form builder.

Ie I have entity form path like so: /tilaus/uusi/{tilaus_type} and I'd like to add additional parameter, like so: /tilaus/uusi/{tilaus_type}/{some_additional_argument}. Preferably in a way that would have both of those urls working and I could handle the missing argument in buildForm method.

I've been searching for a while now, but can't find anything about adding stuff to entity form paths. Normal forms are fine and I know how to handle those. It seems that I just can't figure out the entity routing.

So: How to add additional arguments to entity form url and builder?

Cheers,

Janne

2

An entity add form is built with a new entity. And when you create this entity you can use parameters for this. See this example from the block module.

The new route with the additional parameter:

block.routing.yml

block.admin_add:
  path: '/admin/structure/block/add/{plugin_id}/{theme}'
  defaults:
    _controller: '\Drupal\block\Controller\BlockAddController::blockAddConfigureForm'
    theme: null
    _title: 'Configure block'
  requirements:
    _permission: 'administer blocks'

This adds the parameter theme.

And the controller for this route:

BlockAddController.php

 public function blockAddConfigureForm($plugin_id, $theme) {
    // Create a block entity with prepopulated values.
    $entity = $this->entityManager()->getStorage('block')->create([
      'plugin' => $plugin_id,
      'theme' => $theme,
    ]);

    return $this->entityFormBuilder()->getForm($entity);
  }

Here the additional parameter theme is used when creating the entity.

Using both routes at the same time is no problem, the standard entity route configured in the entity annotations will still be in place.

Another way to use parameters in entity forms is in the third parameter $form_state_additions:

$form_state_additions['langcode'] = $langcode;
$form = \Drupal::service('entity.form_builder')->getForm($entity, 'default', $form_state_additions);

This example is from the source of the entity formbuilder:

https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21EntityFormBuilderInterface.php/8.2.x

  • So this solution is basically Controller and then building a form manually. This is actually what I thought but didn't understand the entityManager / entityFormBuilder usage. I'm going to go ahead and test all suggested methods here and then report back what worked best. – Janne Suominen Nov 2 '16 at 14:15
  • Yes, the entityFormBuilder is injected in the controller class for this task. The controller gives you an extra layer where you can put custom code and prepare the parameters for either using them in the newly created entity or put them in $form_state. – 4k4 Nov 2 '16 at 14:26
  • Hey this worked like a charm! I decided to go with $form_state_additions, seems bit clearer solution to me. Thanks a bunch! – Janne Suominen Nov 2 '16 at 14:48
1

You are asking two questions here. I've tried to answer both in general terms for all forms, and provided specifics for entity forms which are a bit special.

1. How do I handle options parameters in routes?

This is fairly simple, you can provide a default value for the route, say you had a routing file looking something like this

some.route:
  path: '/foo/{bar}/{baz}'
  defaults:
    baz: 42
  ...

using defaults you can specify default values for the parameters. You can specify as many default values as you like, and Drupal will catch it, when there is no more unknown parameters. In the above example you would need to specify a value for bar so

  • foo/some-value
  • foo/some-value/42

would both give same result

2. How do I add additional parameters to en (entity) form?

Solution a

There are two ways to do this. You can add additional parameters in getForm on the form builder which will be available in the ::buildForm method. The EntityFormBuilder is a bit special in that it already has some support for this, the 3 argument to get form is array with data, which will be added to FormState which is used for ::buildForm and ::form

In code (for entity form class) it looks like this

$form = \Drupal::service('entity.form_builder')->getForm($entity, 'default', ['bar' => 'some_data']);

and in the entity form class

public function form(array $form, FormStateInterface $form_state) {
  $storage = $form_state->getStorage();
  $storage['bar'] == 'some_data';
}

Solution b

The other method is often a bit more complex. Instead of using the entity form build, you can instantiate the form class and add whatever you want in the ::__construct. Entity forms are are bit special as they don't have constructors, instead they have setters and a method to get the form class.

In code you entity forms, it could look like this

$form_object = \Drupal::entityTypeManager->getFormObject($entity_id, $operation);
$form_object->setEntity($entity);
$form_object->setCustomValue($value);
$form_render = \Drupal::formBuilder->getForm($form_object);

The advantage with this latter method, is that the data you add to the form class, will be available in all method calls. One issue could be that you need to display multiple variations of the same form on the same page. For Drupal to do this, they need a unique form id, which could be handled in the getFormId method. Or maybe you need to use a service, where it would be messy to use the form building method to store it some where and pass it through the submission process.

  • Thanks for the response.. Solution b looks like the way to go. However, I'm getting Error: Call to undefined method Drupal\\Core\\Entity\\EntityTypeManager::setEntity().. This may be because of I don't fully understand the first line, I suppose that $entity_id is entity type string? – Janne Suominen Nov 2 '16 at 14:38
  • @JanneSuominen Corrected the code. SO engine is not that good for bigger posts with a lot of text/code. Was missing a method call on the entityTypeManager – googletorp Nov 2 '16 at 16:15
0

You can access any request parameter directly in form builder as follows:

/**
 * {@inheritdoc}
 */
public function form(array $form, FormStateInterface $form_state) {

  $some_additional_argument = $this->getRequest()->get('some_additional_argument');

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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