0

I am wanting to embedd a form into a twig template, but place the elements where and how I want them. The idea is to have better control over the layout without having to use the $form array to include #markup.

This page will not only have the form on it. It will also display a table of recently entered data.

I started with this in my controller

    public function index() {
    $form = \Drupal::formBuilder()->getForm('Drupal\rmdrs\Form\ReminderForm');

    return array (
      '#theme' => 'rmdrs_home',
      '#reminder_form' => $form,
    );
  }

Doing this I then went to the .module file and added this:

    function rmdrs_theme($existing, $type, $theme, $path) {
  return array(
    'rmdrs_home' => array(
      'variables' => array(
        'reminder_form' => null,
      ),
    ),
  );
}

There will be other templates for other pages of this module/app that will use this same process.

In my Twig file I call the individual elements like in this sample:

    <div class="rmdrs-form-row-flex form-group-bottom-separator">
    <div style="width: 45%;">
      {{ reminder_form.title }}
    </div>
    <div style="width: 45%;">
      {{ reminder_form.category }}
    </div>
  </div>

The problem is that these elements are not wrapped within a form tag. I am curious how do I get this to work without having to manually wrap the code in a form tag? Shouldn't there be a peice of code that places all this within a form tag?

4
  • 1
    Yes, this is indeed the wrong template level. You are nesting another template outside of the form, but you need to nest a template inside via the $form['#theme'] key of the form build. See drupal.stackexchange.com/questions/245127/…
    – 4uk4
    Commented Nov 14, 2023 at 22:15
  • Does this answer your question? How to render specific form elements from the *.theme file
    – mona lisa
    Commented Nov 14, 2023 at 22:38
  • The information described in the other question you referenced appears to be for a page with a form only. I'm new to Drupal 10, though I have some experience from D7. To complicate things, I am more of a backend PHP person, so theming is a weak spot for me. How do I bring the form into this module page, while having other things on the page too. In the end the form will be opened in a modal when a button is clicked.
    – Cy Jobes
    Commented Nov 15, 2023 at 15:38
  • They are not mutually exclusive, you can use both templates. With "the wrong template level" I was referring to the styling of individual form elements. The controller can put the entire form in its own template. In between those two would then be the form wrapper template all forms have to render the <form> tag. Enable Twig Debugging in the development settings. See drupal.org/docs/develop/theming-drupal/twig-in-drupal/…
    – 4uk4
    Commented Nov 15, 2023 at 21:21

1 Answer 1

0

You have to nest multiple templates, you can't solve this in a single template. See for example the standard node edit form which is rendered as main content in a block, this block renders the form and the form renders the inner template styling the individual form elements. In your case, the block template would be the controller template.

Visit www.example.com/node/8/edit and press CTRL-U to see the HTML source. If you have the Twig debug mode enabled, you see the nested templates in the comments:

<!-- BEGIN OUTPUT from 'core/themes/claro/templates/classy/block/block.html.twig' -->
<div id="block-claro-content" class="block block-system block-system-main-block">

<!-- BEGIN OUTPUT from 'core/modules/system/templates/form.html.twig' -->
<form class="node-article-edit-form node-form" data-drupal-selector="node-article-edit-form" enctype="multipart/form-data" action="/node/8/edit" method="post" id="node-article-edit-form" accept-charset="UTF-8">

<!-- BEGIN OUTPUT from 'core/themes/claro/templates/node-edit-form.html.twig' -->

This outputs the node-edit-form.html.twig, which contains some helpful information in the doc block:

{#
/**
 * @file
 * Theme override for a node edit form.
 *
 * Two column template for the node add/edit form.
 *
 * This template will be used when a node edit form specifies 'node_edit_form'
 * as its #theme callback.  Otherwise, by default, node add/edit forms will be
 * themed by form.html.twig.
 *
 * Available variables:
 * - form: The node add/edit form.
 *
 * @see claro_form_node_form_alter()
 */
#}
<div class="layout-node-form clearfix">
  <div class="layout-region layout-region--node-main">
    <div class="layout-region__content">
      {{ form|without('advanced', 'footer', 'actions') }}
    </div>
  </div>
  <div class="layout-region layout-region--node-secondary">
    <div class="layout-region__content">
      {{ form.advanced }}
    </div>
  </div>
  <div class="layout-region layout-region--node-footer">
    <div class="layout-region__content">
      <div class="divider"></div>
      {{ form.footer }}
      {{ form.actions }}
    </div>
  </div>
</div>

To implement this for a custom form see How to render specific form elements from the *.theme file

4
  • The HOOK_theme in the link titled "How to render specific form elements from the *.theme file" is written in such a way that it only spits out a form. The page being built is more than just a form. My Controller will be sending variable data to the HOOK_theme to build more items on the template. Also, this is not the only thing that will be referenced in the HHOK_theme, so it need to be written to allow for more. I need to know how to write the the HOOK_theme and anything else to build the entire page. Make sense?
    – Cy Jobes
    Commented Nov 16, 2023 at 14:39
  • You can't send data to hook_theme, this is only called when the theme registry is rebuilt, which never happens in a normal request. This might be about the general concept of form rebuilds. While rebuilding you have the form values in $form_state and you put anything you want to inform the user about in the form build. The final submit stores the data in the database and the redirect destination reads it from the database and displays it.
    – 4uk4
    Commented Nov 16, 2023 at 15:00
  • Admittedly I don’t know how HOOK_theme works. It’s a means to an end. I’ve been a PHP dev for 20+ years. Using Laravel, for example, I could call a template within a class method, render it, then pass it to a variable that is used to help build the page. I find it hard to believe Drupal does not have something similar, which is what I am trying to achieve - render a form, to pass to the template used to display the page. Also, I learn by baptism-by-fire. Not fun when answers are so difficult to find. I appreciate your help, and anything further you can do to help me put out this fire! :)
    – Cy Jobes
    Commented Nov 16, 2023 at 16:43
  • OK, I can only answer one question at a time like how to style individual elements in a Drupal form.
    – 4uk4
    Commented Nov 16, 2023 at 17:17

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.