1

Very hard to explain by title, but this is what I mean:

I have a form which shows packages and their add-ons. A simplified version:

foreach ($packages as $package) {
  $form['package_' . $package->nid] = array(
    '#prefix' => '<div class="container-select package">',
    '#suffix' => '</div>',
    '#tree' => TRUE,
  );
  $form['package_' . $package->nid]['select'] = array(
    '#type' => 'radio',
    '#return_value' => 'package_' . $package->nid,
    '#prefix' => '<div class="package_select">',
    '#suffix' => '</div>',
    '#tree' => FALSE,
  );
  $form['package_' . $package->nid]['title'] = array(
    '#prefix' => '<div class="package_title">',
    '#markup' => $package->title,
    '#suffix' => '</div>',
  );
  $form['package_' . $package->nid]['addons'] = array(
    '#type' => 'container',
    '#prefix' => '<div class="package_addons">',
    '#suffix' => '</div>',
  );
  foreach ($addons as $addon) {
    $form['package_' . $package->nid]['addons']['addon_' . $addon->nid] = array(
      '#prefix' => '<div class="container-select addon'">',
      '#suffix' => '</div>',
    );
    $form['package_' . $package->nid]['addons']['addon_' . $addon->nid]['select'] = array(
      '#type' => 'checkboxes',
      '#options' => array($addon->nid => $addon->title),
      '#return_value' => 'addon_' . $addon->nid,
      '#prefix' => '<div class="addon_select">',
      '#suffix' => '</div>',
      '#tree' => TRUE,
    );
    $form['package_' . $package->nid]['addons']['addon_' . $addon->nid]['title'] = array(
      '#prefix' => '<div class="addon_title">',
      '#markup' => $addon->title,
      '#suffix' => '</div>',
    );
  }
}

This results in the following HTML:

<div class="container-select package">
  <div class="package_select">...</div>
  <div class="package_title">...</div>
  <div class="package_addons">
    <div class="container-select addon">
      <div class="addon_title">...</div>
    </div>
    <div class="container-select addon">
      .. second addon .. and so on ..
    </div>
  </div>
</div>
<div class="container-select package">
.. second package .. and so on .. 
</div>

The problem is that I want the add-ons to be displayed BELOW the package container it belongs to, but still have the values within the tree. So I want:

<div class="container-select package">
  <div class="package_select">...</div>
  <div class="package_title">...</div>
</div>
<div class="package_addons">
  <div class="container-select addon">
    <div class="addon_title">...</div>
  </div>
  <div class="container-select addon">
    .. second addon .. and so on ..
  </div>
</div>
<div class="container-select package">
.. second package .. and so on .. 
</div>

I thought about doing this with CSS first. But it's getting a mess. Second I thought about using jQuery to move the package_addons element. But actually I hope there is a better solution by Drupal / PHP, so I don't have to mess around with CSS or jQuery.

Any thoughts?

  • You can provide your own #theme function for any FAPI element (including the top level of a tree). drupal.stackexchange.com/questions/312/… contains some useful code maybe that can get you started? – Clive Apr 14 '15 at 17:22
  • Thanks for your answer. But I don't see how using #theme can change the order of my elements. – Rene Apr 15 '15 at 11:01
  • With #theme you're building the HTML yourself - the elements will be in whatever order you decide to write them in – Clive Apr 15 '15 at 11:11
  • While I couldn't find the right way with using #theme in the first place I found another solution changes the logic within the form itself. – Rene Apr 29 '15 at 8:57
  • After having another issue I can finally see how I could have arranged the files differently by using #theme and my own template: Using this code in your .tpl file helps rendering the fields in the order you want: print drupal_render_children($form['specific_field']); print drupal_render_children($form); The 'specific_field' will be rendered first and won't be rendered again while the whole form will be rendered on the second line. – Rene Apr 29 '15 at 9:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.