Drupal - How do I embed a form in a controller response?
To embed a form in a renderable array, you use:
$form_class = '\Drupal\my_module\Form\MyForm';
$build['form'] = \Drupal::formBuilder()->getForm($form_class);
Which is similar to your code.
But the problem is of a different nature. You are extending a special controller, one that returns a renderable array of '#type' => 'page'
. It uses the page template to render the output and that template does not contain the {{ layout_control }}
variable to output your form. If you use $page['header']['layout_control'] = ...
to add the form to the render array, it should show the form in the header region of the layout demo page.
You can render a form and place it wherever you want in your markup.
In your controller method, you want to do $this->formBuilder()->getForm()
and then render that form array using \Drupal::service('renderer')->render()
I'm not sure what side effects this might have with submission / error control if you have multiple forms on a single page but it is possible to do it.
See below controller
<?php
namespace Drupal\my_module\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Render\Markup;
class MyController extends ControllerBase
{
public function displayForm()
{
$myForm = $this->formBuilder()->getForm('Drupal\my_module\Form\MyForm');
$renderer = \Drupal::service('renderer');
$myFormHtml = $renderer->render($myForm);
return [
'#markup' => Markup::create("
<h2>My Form is Below</h2>
{$myFormHtml}
<h2>My Form is Above</h2>
")
];
}
}
So it turns out that Drupal 8 doesn't let you to do the kind of loose, willy-nilly page alteration that Drupal 7 allowed. Instead, you have to use one of the hooks which replace hook_page_build() and hook_page_alter(). In particular, hook_page_top() and hook_page_bottom() are where you can insert arbitrary renderable elements.
There's an API change record explaining this: https://www.drupal.org/node/2357755.
Here's the code I used to fix my problem (in the .module file):
/**
* Implements hook_page_bottom().
*/
function block_ui_page_bottom(array &$page_bottom) {
$route_match = \Drupal::routeMatch();
if ($route_match->getRouteName() == 'block.admin_display_theme') {
$region_list = system_region_list($route_match->getParameter('theme'), REGIONS_VISIBLE);
$form_state = new FormState();
$form_state->set('region_list', $region_list);
$page_bottom['layout_control'] = \Drupal::formBuilder()->buildForm('\Drupal\block_ui\Form\LayoutControlForm', $form_state);
}
}