3

Question: When adding a field via hook_form_alter, how do you control the order in the HTML which the field is rendered?

Meaning, this is my current hook_form_alter:

function ccom_validations_form_challenges_node_form_alter(&$form, &$form_state, $form_id) {
  $form['my_field'] = array (
    '#type' => 'hidden',
    '#value' => 'schweet'
  );
  dpm($form);
}

...which adds the hidden form element to the end of the renderable array. That's cool. However, this is what my HTML looks like...

<div><input type="hidden" name="changed" value="">
<input type="hidden" name="form_build_id" value="form-ToT93ljrNzFudWQnMVF0Ti4-RLmTXPt8AhusXxR2Tcc">
<input type="hidden" name="form_token" value="RXnp5FVFnZgTcRn_lsDfBDzze6IcOnEwx_7ok6J70Z4">
<input type="hidden" name="form_id" value="challenges_node_form">
<input type="hidden" name="my_field" value="schweet">
<div class="field-type-taxonomy-term-reference field-name-field-reporting-period field-widget-options-select form-wrapper" id="edit-field-reporting-period"><div class="form-item form-type-select form-item-field-reporting-period-und">
  <label for="edit-field-reporting-period-und">Reporting Period <span class="form-required" title="This field is required.">*</span></label>
 <select id="edit-field-reporting-period-und" name="field_reporting_period[und]" class="form-select required"><option value="1342" selected="selected">2012 December</option><option value="56">2012 June</option></select>
</div>
</div><div class="field-type-text-with-summary field-name-body field-widget-text-textarea-with-summary form-wrapper" id="edit-body"><div id="body-add-more-wrapper"><div class="text-format-wrapper"><div class="text-summary-wrapper text-summary-wrapper-processed" style="display: none; "><div class="form-item form-type-textarea form-item-body-und-0-summary">
  <label for="edit-body-und-0-summary">Summary </label>
<div class="description">Leave blank to use trimmed value of full text as the summary.</div>
 <div class="form-textarea-wrapper resizable textarea-processed resizable-textarea"><textarea class="text-summary form-textarea text-summary-processed" id="edit-body-und-0-summary" name="body[und][0][summary]" cols="60" rows="5"></textarea><div class="grippie"></div></div>
</div>
</div><div class="form-item form-type-textarea form-item-body-und-0-value">
  <label for="edit-body-und-0-value">Description of Challenges <span class="form-required" title="This field is required.">*</span><span class="field-edit-link">(<a class="link-edit-summary" href="#">Edit summary</a>)</span></label>
 <div class="form-textarea-wrapper resizable textarea-processed resizable-textarea"><textarea class="text-full form-textarea required" id="edit-body-und-0-value" name="body[und][0][value]" cols="60" rows="20"></textarea><div class="grippie"></div><div class="wysiwyg-toggle-wrapper"><a id="wysiwyg-toggle-edit-body-und-0-value" href="javascript:void(0);" style="display: none; ">Disable rich-text</a></div></div>
</div>
<fieldset class="filter-wrapper form-wrapper" id="edit-body-und-0-format"><div class="fieldset-wrapper"><div class="filter-help form-wrapper" id="edit-body-und-0-format-help"><p><a href="/filter/tips" target="_blank">More information about text formats</a></p></div><div class="form-item form-type-select form-item-body-und-0-format">
  <label for="edit-body-und-0-format--2">Text format </label>
 <select class="filter-list wysiwyg form-select wysiwyg-processed" id="edit-body-und-0-format--2" name="body[und][0][format]"><option value="progress_report_field" selected="selected">Progress Report Field</option><option value="markdown">Markdown</option><option value="filtered_html">Filtered HTML</option><option value="full_html">Full HTML</option><option value="plain_text">Plain text</option></select>
</div>
<div class="filter-guidelines form-wrapper filter-guidelines-processed" id="edit-body-und-0-format-guidelines"><div class="filter-guidelines-item filter-guidelines-progress_report_field" style="display: block; "><h3 style="display: none; ">Progress Report Field</h3><ul class="tips"><li>No HTML tags allowed.</li><li>Lines and paragraphs break automatically.</li><li>Web page addresses and e-mail addresses turn into links automatically.</li></ul></div><div class="filter-guidelines-item filter-guidelines-markdown" style="display: none; "><h3 style="display: none; ">Markdown</h3><ul class="tips"><li>Quick Tips:<ul>
      <li>Two or more spaces at a line's end = Line break</li>
      <li>Double returns = Paragraph</li>
      <li>*Single asterisks* or _single underscores_ = <em>Emphasis</em></li>
      <li>**Double** or __double__ = <strong>Strong</strong></li>
      <li>This is [a link](http://the.link.example.com "The optional title text")</li>
      </ul>For complete details on the Markdown syntax, see the <a href="http://daringfireball.net/projects/markdown/syntax">Markdown documentation</a> and <a href="http://michelf.com/projects/php-markdown/extra/">Markdown Extra documentation</a> for tables, footnotes, and more.</li></ul></div><div class="filter-guidelines-item filter-guidelines-filtered_html" style="display: none; "><h3 style="display: none; ">Filtered HTML</h3><ul class="tips"><li>Web page addresses and e-mail addresses turn into links automatically.</li><li>Allowed HTML tags: &lt;a&gt; &lt;em&gt; &lt;strong&gt; &lt;cite&gt; &lt;blockquote&gt; &lt;code&gt; &lt;ul&gt; &lt;ol&gt; &lt;li&gt; &lt;dl&gt; &lt;dt&gt; &lt;dd&gt;</li><li>Lines and paragraphs break automatically.</li></ul></div><div class="filter-guidelines-item filter-guidelines-full_html" style="display: none; "><h3 style="display: none; ">Full HTML</h3><ul class="tips"><li>Web page addresses and e-mail addresses turn into links automatically.</li></ul></div><div class="filter-guidelines-item filter-guidelines-plain_text" style="display: none; "><h3 style="display: none; ">Plain text</h3><ul class="tips"><li>No HTML tags allowed.</li><li>Web page addresses and e-mail addresses turn into links automatically.</li><li>Lines and paragraphs break automatically.</li></ul></div></div></div></fieldset>
<div class="description">Use this field to document any challenges or obstacles you have experienced whilst working on your research.  This should be a relatively in-depth description.  Use the Summary field to provide highlights.</div></div>
</div></div><h2 class="element-invisible">Vertical Tabs</h2><div class="vertical-tabs clearfix"><ul class="vertical-tabs-list"><li class="vertical-tab-button first selected" tabindex="-1"><a href="#"><strong>URL path settings</strong><span class="summary">Automatic alias</span><span id="active-vertical-tab" class="element-invisible">(active tab)</span></a></li><li class="vertical-tab-button" tabindex="-1"><a href="#"><strong>Revision information</strong><span class="summary">New revision</span></a></li><li class="vertical-tab-button" tabindex="-1"><a href="#"><strong>Comment settings</strong><span class="summary">Closed</span></a></li><li class="vertical-tab-button" tabindex="-1"><a href="#"><strong>Authoring information</strong><span class="summary">By lpeabody</span></a></li><li class="vertical-tab-button last" tabindex="-1"><a href="#"><strong>Publishing options</strong><span class="summary">Published</span></a></li></ul><div class="vertical-tabs-panes vertical-tabs-processed"><fieldset class="path-form form-wrapper vertical-tabs-pane" id="edit-path" style=""><legend><span class="fieldset-legend">URL path settings</span></legend><div class="fieldset-wrapper"><div class="form-item form-type-checkbox form-item-path-pathauto">
 <input type="checkbox" id="edit-path-pathauto" name="path[pathauto]" value="1" checked="checked" class="form-checkbox">  <label class="option" for="edit-path-pathauto">Generate automatic URL alias </label>

<div class="description">Uncheck this to create a custom alias below. <a href="/admin/config/search/path/patterns">Configure URL alias patterns.</a></div>
</div>
<div class="form-item form-type-textfield form-item-path-alias">
  <label for="edit-path-alias">URL alias </label>
<div class="description">Optionally specify an alternative URL by which this content can be accessed. For example, type "about" when writing an about page. Use a relative path and don't add a trailing slash or the URL alias won't work.</div>
 <input type="text" id="edit-path-alias" name="path[alias]" value="" size="60" maxlength="255" class="form-text" disabled="">
</div>
</div></fieldset>
<fieldset class="node-form-revision-information form-wrapper vertical-tabs-pane" id="edit-revision-information" style="display: none; "><legend><span class="fieldset-legend">Revision information</span></legend><div class="fieldset-wrapper"><div class="form-item form-type-checkbox form-item-revision">
 <input type="checkbox" id="edit-revision" name="revision" value="1" checked="checked" class="form-checkbox">  <label class="option" for="edit-revision">Create new revision </label>

</div>
<div class="form-item form-type-textarea form-item-log">
  <label for="edit-log">Revision log message </label>
<div class="description">Provide an explanation of the changes you are making. This will help other authors understand your motivations.</div>
 <div class="form-textarea-wrapper resizable textarea-processed resizable-textarea"><textarea id="edit-log" name="log" cols="60" rows="4" class="form-textarea"></textarea><div class="grippie"></div></div>
</div>
</div></fieldset>
<fieldset class="comment-node-settings-form form-wrapper vertical-tabs-pane" id="edit-comment-settings" style="display: none; "><legend><span class="fieldset-legend">Comment settings</span></legend><div class="fieldset-wrapper"><div class="form-item form-type-radios form-item-comment">
  <label class="element-invisible" for="edit-comment">Comments </label>
 <div id="edit-comment" class="form-radios"><div class="form-item form-type-radio form-item-comment">
 <input type="radio" id="edit-comment-2" name="comment" value="2" class="form-radio">  <label class="option" for="edit-comment-2">Open </label>

<div class="description">Users with the "Post comments" permission can post comments.</div>
</div>
<div class="form-item form-type-radio form-item-comment">
 <input type="radio" id="edit-comment-1" name="comment" value="1" checked="checked" class="form-radio">  <label class="option" for="edit-comment-1">Closed </label>

<div class="description">Users cannot post comments.</div>
</div>
</div>
</div>
</div></fieldset>
<fieldset class="node-form-author form-wrapper vertical-tabs-pane" id="edit-author" style="display: none; "><legend><span class="fieldset-legend">Authoring information</span></legend><div class="fieldset-wrapper"><div class="form-item form-type-textfield form-item-name" role="application">
  <label for="edit-name">Authored by </label>
<div class="description">Leave blank for <em class="placeholder">Anonymous</em>.</div>
 <input type="text" id="edit-name" name="name" value="lpeabody" size="60" maxlength="60" class="form-text form-autocomplete" autocomplete="OFF" aria-autocomplete="list"><input type="hidden" id="edit-name-autocomplete" value="https://intranet.webdev.ccom.nh/user/autocomplete" disabled="disabled" class="autocomplete autocomplete-processed">
<span class="element-invisible" aria-live="assertive" id="edit-name-autocomplete-aria-live"></span></div>
<div class="form-item form-type-textfield form-item-date">
  <label for="edit-date">Authored on </label>
<div class="description">Format: <em class="placeholder">2012-10-11 17:23:38 -0400</em>. The date format is YYYY-MM-DD and <em class="placeholder">-0400</em> is the time zone offset from UTC. Leave blank to use the time of form submission.</div>
 <input type="text" id="edit-date" name="date" value="" size="60" maxlength="25" class="form-text">
</div>
</div></fieldset>
<fieldset class="node-form-options form-wrapper vertical-tabs-pane" id="edit-options" style="display: none; "><legend><span class="fieldset-legend">Publishing options</span></legend><div class="fieldset-wrapper"><div class="form-item form-type-checkbox form-item-status">
 <input type="checkbox" id="edit-status" name="status" value="1" checked="checked" class="form-checkbox">  <label class="option" for="edit-status">Published </label>

</div>
<div class="form-item form-type-checkbox form-item-promote">
 <input type="checkbox" id="edit-promote" name="promote" value="1" class="form-checkbox">  <label class="option" for="edit-promote">Promoted to front page </label>

</div>
<div class="form-item form-type-checkbox form-item-sticky">
 <input type="checkbox" id="edit-sticky" name="sticky" value="1" class="form-checkbox">  <label class="option" for="edit-sticky">Sticky at top of lists </label>

</div>
</div></fieldset>
<input class="vertical-tabs-active-tab" type="hidden" name="additional_settings__active_tab" value="edit-path">
</div></div><div class="form-actions form-wrapper" id="edit-actions"><input type="submit" id="edit-submit" name="op" value="Save" class="form-submit"><input type="submit" id="edit-preview" name="op" value="Preview" class="form-submit"></div></div>

Really the most important part is that even though the element appeared last in the array, it shows up as the last hidden element at the very top of that code, on line 5 to be specific.

It is very important that this field get's rendered after all other fields. How can this be done "the Drupal 7 way"? Using DOM manipulation via JavaScript is not an option (and shame on you if you think it is).

3

You can use the #weight property to control the display order of elements in a form (or any render array as it happens).

Elements with lower weight will appear first (and vice versa) so

$form['my_field'] = array (
  '#type' => 'hidden',
  '#value' => 'schweet',
  '#weight' => 1000
);

will make sure your element is right at the bottom, for example.

You can also alter the #weight of any other elements in the form so you should be able to rearrange it exactly as you need.

| improve this answer | |
  • I actually discovered this, like, 10 minutes after I posted this. So, props :) Schweeeet. – Lester Peabody Oct 12 '12 at 2:38
3

Give the form element a weight. Also to make sure it shows up after all the fields make sure you set the weight greater than all the fields using field_info_max_weight. This will make sure it will show up at the very end even if you add new fields in the future.

So it might look something like this

function ccom_validations_form_challenges_node_form_alter(&$form, &$form_state, $form_id) {
  $form['my_field'] = array (
    '#type' => 'hidden',
    '#value' => 'schweet'
    '#weight' => field_info_max_weight('node', 'challenges', 'form') + 10,
  );
}

Let me know if it works.

| improve this answer | |

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.