0

I've got an input field in an entity form which needs quite a bit of extra documentation. This documentation is long and needs computed, contextual information, so a simple field description or #field_suffix just doesn't do it. I also want to keep the ability to move fields around in field UI. I'm trying to create a form_alter hook to inject a render element with my docs right after that field.

I already have a working prototype:

function MYMODULE_form_ENITY_FORMMODE_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $fieldToEnhance = 'field_foo';
  if (!isset($form[$fieldToEnhance])) {
    return;
  }
  $computedDocumentationVariables = mymodule_get_infos();
  $renderElementToAppend[$fieldToEnhance . '_append'] = [
    '#type' => 'inline_template',
    '#template' => '<div>This is a very shortened and simplified placeholder.</div>',
    '#context' => $computedDocumentationVariables,
    '#parents' => $form[$fieldToEnhance]['#parents'] ?? [],
    '#weight' => isset($form[$fieldToEnhance]['#weight']) ? $form[$fieldToEnhance]['#weight'] + 1 : NULL,
  ];
  $positionOfField = array_search($fieldToEnhance, array_keys($form));
  // inject the render element right after the field in the form array
  $form = array_merge(
    array_merge(
      array_slice($form, 0, $positionOfField+1),
      $renderElementToAppend
    ),
    $form
  );
}

This works as exptected for a very plain form.

But as soon as I move my field inside a container from Field group module, the positioning doesn't work as expected. When viewing it in a debugger, I can see that my custom render element is at the correct position inside the $form array. But on screen it is not rendered at the correct position. (My documentation render element is on root level. I want it inside the container, right after the field.)

How do I make my hook aware of potential nesting containers from Field Group module?

2
  • a simple field description doesn't do it ... I don't think there is a limitation on what you can put in #description. This variable is printed in the field wrapper template below the field. You can change the position in the template, but I wouldn't change the form array structure if you want the form to work with other modules.
    – 4uk4
    May 8, 2023 at 12:09
  • I can't inject a render array neither in field descriptions nor the suffix. My desired solution is a render array containing multiple inline templates inside collapsible details elements.
    – Hudri
    May 8, 2023 at 12:46

1 Answer 1

0

#suffix and #description are very different. The first one is a Render API standard property common to all render elements and is handled by the Renderer service. The second one is handled as a normal template variable with no restrictions on the number of render elements or nesting levels. You only have to ensure it is printed the way you set it. Check Twig Debug to see which template is used. The standard form-element.html.twig is rendering a subkey content. Some input elements use their own wrapper template/preprocessing and don't have this subkey. You can also define a custom wrapper template with your own set of variables.

5
  • I was overthinking this. In my initial tests I simply was on the wrong "level" in the render array, "going deeper" in the render array of the field solved all my issues.
    – Hudri
    May 8, 2023 at 15:10
  • #description is a form element property too, described in FormElement (which does not list the properties in common with other render elements, listed in RenderElement). It is also used by most of the form elements.
    – apaderno
    May 9, 2023 at 5:17
  • 1
    Still, #suffix and #description are handled very differently. Only the second one is subjected to preprocessing and is printed as a template variable. I've tried to make the wording more clear.
    – 4uk4
    May 9, 2023 at 6:29
  • form-element.html.twig gets both suffix and description. The difference is that the value of #description is available as description.content while the content of #suffix is available as suffix. Indeed, they are handled differently, but they are both available to preprocessing and to the template file.
    – apaderno
    May 9, 2023 at 15:35
  • No, the content of #field_suffix is available as suffix. Then this is a normal template variable and can print nested render arrays. Strange they use the name of the reserved Render API property #suffix, which by the way still works the same as in any other template and has the restrictions I've described.
    – 4uk4
    May 10, 2023 at 6:59

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.