There are several attempts and questions already asked about near to that topic in combination with the new Drupal core (8), but non of them came down to the bottom of the basic question. And non of them are up-to-date enough (2015) since many late changes in core arrived afterwards (2016). Answering the basic question will hopefully lead to answers for many depending questions and open HOWTO topics and could be a good basis for updated docs on drupal.org.
The basic question is:
How to programmatically render path/page based forms or any other entity bundles on the theming level to display them path independently, e.g. in blocks or other pages other than the given pages/paths of itself? And how can I find the right routing for the correct system calls or class paths for the needed preprocess functions in the new D8 core logic if I am new to D8?
The question arises from 2 points of view:
Why should a form be hard binded to a page view or fixed path? It's a page element, not a page. It should be available easely in any other places without complicated coding struggles in a website building CMF like Drupal on the theming level. It's part of theme design to decide to have a form on frontpage, for example. (ok, this is arguable, I know, but in some cases it is)
From the basic structure how Drupal is build and what it tries to achieve in these times (the goal to rather build web applications instead of classic and static websites), it should be easily reachable to maintain such task like a form on the bottom of a one-page site or to build a survey or render entities on unexpected pages.
To keep with the form example:
here are some links to questions regarding this topic and I've tried already to interfere there and suggest to inform about changes in core here and there to update the posts or to link to sources:
- How to programmatically render a contact form in a theme in D8
- Rendering contact_form
- Embed a contact form
The basic structure
.. how it works is common, mostly clear, and not so far from how it worked in D7:
You will use a preprocess_xxx()
function in your D8 twig YOURTHEMENAME.theme
file to call and pipe the form or entity array into the region variable array, to be able to render it via {{ var }}
twig-tags in your xxx.twig file: e.g. block.html.twig
or page.html.twig
, since the form or entity is maybe not known in this layer (enviroment variable) by default.
Just an example (needs update and correction) of your THEMENAME.theme file:
preprocess_page(){
$form = Drupal::routeMatch()->getParameter('contact_form'); // ???
$message = \Drupal::entityTypeManager() // ???
->getStorage('contact_message')
->create(array(
'contact_form' => $form->id(),
));
/// ???
$form = Drupal::service('entity.form_builder')->getForm($message);
$variables['contact_form'] = $form;
}
Just an example page.html.twig file:
<header>
{{ header_region }}
</header>
<div id="main"> ... </div>
<footer>
{{ contact_form }} <!-- from $variables['contact_form'] = $form; -->
</footer>
But now comes the tricky part:
The docs are not up-to-date enough to make clear how to build the preprocess_xxx()
function correctly, demonstrated with \\ ???
here. Using the demo example here as-is (atm) will cause an almost empty frontpage, only rendering html.html.twig but without the nested page.html.twig, obviously caused by a wrong coding in the preprocess function.
Somebody who tries to find updated docs or QA for that will have a hard time ...