The best solution:
This is the default comment-wrapper.tpl.php
:
<?php if ($content['comment_form']): ?>
<h2 class="title comment-form"><?php print t('Add new comment'); ?></h2>
<?php print render($content['comment_form']); ?>
<?php endif; ?>
If you want to modify the form elements by overriding the template file, here is the best known way:
<?php if ($content['comment_form']): ?>
<h2 class="title comment-form"><?php print t('Add new comment'); ?></h2>
<?php
// 1. Create a custom markup
$form_custom_markup = '';
$form_custom_markup .= '<div style="background-color: red;">';
$form_custom_markup .= render($content['comment_form']['author']);
$form_custom_markup .= '</div>';
$form_custom_markup .= '<div style="background-color: blue;">';
$form_custom_markup .= render($content['comment_form']['comment_body']);
$form_custom_markup .= '</div>';
// 2. Attach the custom markup to the form
$content['comment_form']['custom_markup'] = array(
'#type' => 'markup',
'#markup' => $form_custom_markup
);
?>
<?php print render($content['comment_form']); ?>
<?php endif; ?>
In this example we make the Author field appear in red background and the comment body in blue background!
You could simply modify the sample above to re-arrange any form element in your form.
Why the normal way didn't work?
To understand this solution and other solutions first we need to understand why forms
behave differently than other render arrays
.
To start let us have a look at the function that renders a form:
<?php
// form.inc
function theme_form($variables) {
$element = $variables['element'];
if (isset($element['#action'])) {
$element['#attributes']['action'] = drupal_strip_dangerous_protocols($element['#action']);
}
element_set_attributes($element, array('method', 'id'));
if (empty($element['#attributes']['accept-charset'])) {
$element['#attributes']['accept-charset'] = "UTF-8";
}
// Anonymous DIV to satisfy XHTML compliance.
return '<form' . drupal_attributes($element['#attributes']) . '><div>' . $element['#children'] . '</div></form>';
}
As you see, when you render($form)
it wraps it with ''. It means that any elements that have been rendered before will be out of <form>
. That was why when you render render($form['actions'])
before render($form)
even buttons stop working, because they are out of the <form>
element!
What are other solutions?
Using HOOK_preprocess_hook()
As you could see we modified $content['comment_form']. You could do the same thing by using the template preprocess function
:
/**
* Implements HOOK_preprocess_hook()
* Preprocess variables for comment-wrapper.tpl.php
*/
function THEME_preprocess_comment_wrapper(&$vars) {
if ($vars['node']->type == 'article') {
$form_custom_markup = '';
$form_custom_markup .= '<div style="background-color: green;">';
$form_custom_markup .= render($vars['content']['comment_form']['author']);
$form_custom_markup .= '</div>';
$form_custom_markup .= '<div style="background-color: red;">';
$form_custom_markup .= render($vars['content']['comment_form']['comment_body']);
$form_custom_markup .= '</div>';
// Attach the custom markup to the form
$vars['content']['comment_form']['custom_markup'] = array(
'#type' => 'markup',
'#markup' => $form_custom_markup
);
}
}
This example overrides form elements of comment form on article
pages.
Tip: You should replace THEME
with your theme name and put this function in template.php
in you theme folder.
Using HOOK_preprocess_hook()
If you trace where the element is actually generated you will get to this lines in comment.module
:
$build = drupal_get_form("comment_node_{$node->type}_form", (object) array('nid' => $node->nid));
$additions['comment_form'] = $build;
We can see this is a form with the form_id
of comment_node_NODE_TYPE_form
. So we could use hook_form_alter
to alter form elements:
/**
* Implements hook_form_alter()
*/
function THEME_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'comment_node_article_form') {
// Play around with $form
}
}
In this example we are altering the comment form for article
nodes.
Tip: Generally using form_alter
to change the display of the form is not recommended because it also affects the form_submit()
and form_validate()
and may cause unwanted issues in future or conflict with other modules.