J'ai un contrôleur qui retourne un tableau de pages affichable normal. Je voudrais incorporer un formulaire dans cette page, mais le formulaire n'apparaît pas dans la sortie rendue. Le formulaire est correctement ajouté au tableau de rendu correctement, mais il n'est pas dans le code HTML final pour une raison quelconque. Que se passe t-il ici?
Voici mon contrôleur (qui étend ControllerBase via BlockController):
use Drupal\block\Controller\BlockController;
use Drupal\Core\Extension\ThemeHandlerInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Render\Element;
use Symfony\Component\DependencyInjection\ContainerInterface;
class LayoutController extends BlockController {
/**
* @var \Drupal\Core\Form\FormBuilderInterface
*/
protected $formBuilder;
/**
* {@inheritdoc}
*/
public function __construct(ThemeHandlerInterface $theme_handler, FormBuilderInterface $form_builder) {
parent::__construct($theme_handler);
$this->formBuilder = $form_builder;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('theme_handler'),
$container->get('form_builder')
);
}
/**
* Overrides the region demo page, adding placeholder elements for sortable
* lists of blocks, plus a control panel form.
*
* @param string $theme
* The theme key.
*
* @return array
* The renderable page.
*/
public function layout($theme) {
$page = parent::demo($theme);
foreach (Element::children($page) as $region) {
if (isset($page[$region]['block_description'])) {
$page[$region]['block_description']['#template'] .= '<ul data-region="{{ region }}"></ul>';
$page[$region]['block_description']['#context']['region'] = $region;
}
}
$page['layout_control'] = $this->formBuilder->getForm('Drupal\block_ui\Form\LayoutControlForm');
$page['#attached']['library'][] = 'block_ui/backbone.collectionView';
return $page;
}
}
Pour incorporer un formulaire dans un tableau pouvant être rendu, vous utilisez:
$form_class = '\Drupal\my_module\Form\MyForm';
$build['form'] = \Drupal::formBuilder()->getForm($form_class);
Qui est similaire à votre code.
Mais le problème est de nature différente. Vous étendez un contrôleur spécial, celui qui renvoie un tableau pouvant être rendu de '#type' => 'page'
. Il utilise le modèle de page pour restituer la sortie et ce modèle ne contient pas la variable {{ layout_control }}
Pour sortir votre formulaire. Si vous utilisez $page['header']['layout_control'] = ...
Pour ajouter le formulaire au tableau de rendu, il doit afficher le formulaire dans la région d'en-tête de la page de démonstration de la disposition.
Vous pouvez rendre un formulaire et le placer où vous le souhaitez dans votre balisage.
Dans votre méthode de contrôleur, vous voulez faire $this->formBuilder()->getForm()
puis rendre ce tableau de formulaire en utilisant \Drupal::service('renderer')->render()
Je ne sais pas quels effets secondaires cela pourrait avoir avec le contrôle des soumissions/erreurs si vous avez plusieurs formulaires sur une seule page, mais il est possible de le faire.
Voir ci-dessous contrôleur
<?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>
")
];
}
}
Il s'avère donc que Drupal 8 ne vous permet pas de faire le genre de modification de page lâche et bon gré mal gré Drupal 7 autorisé. Au lieu de cela, vous doivent utiliser l'un des crochets qui remplacent hook_page_build () et hook_page_alter (). En particulier, hook_page_top () et hook_page_bottom () sont l'endroit où vous pouvez insérer des éléments arbitraires rendables.
Il y a un enregistrement de changement d'API expliquant cela: https://www.drupal.org/node/2357755 .
Voici le code que j'ai utilisé pour résoudre mon problème (dans le fichier .module):
/**
* 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);
}
}