Is there a way to add placeholders to a form with a module, or should this be done with a form template?
7 Answers
That's an HTML5 placeholder, you can just add it as an attribute to any element and HTML5 enabled browsers will react accordingly:
function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'some_form') {
$form['some_element']['#attributes']['placeholder'] = t('Placeholder text');
}
}
A short recursive function like this might be handy if you want to automatically add placeholders for every textfield in a form (based on the field's title in this example):
function MYMODULE_auto_placeholders(&$element) {
if ( isset($element['#type']) && $element['#type'] == 'textfield') {
// set placeholder
$element['#attributes']['placeholder'] = $element['#title'];
// hide label
$element['#title_display'] = 'invisible';
}
foreach (element_children($element) as $key) {
MYMODULE_auto_placeholders($element[$key]);
}
}
Then in your form alter function just call
MYMODULE_auto_placeholders($form);
That method will work for pretty much every textfield on a form, with the exception of those that are added in #process
functions (like the alt and title textfields of an image field for example).
Just add the placeholder in the #attributes array for the form field element, such as in the following code.
$form['my_textfield'] = array(
'#type' => 'textfield',
'#attributes' => array(
'placeholder' => t('My placeholder text'),
),
);
I tried Clive's answer:
function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'some_form') {
$form['some_element']['#attributes']['placeholder'] = t('Placeholder text');
}
}
But to my surprise, I got the placeholder in wrapper of textfield, not textfield itself. Then I tried a variation as follows, it worked!
function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'some_form') {
$form['some_element']['und'][0]['value']['#attributes']['placeholder'] = t('Placeholder text');
}
}
-
Thanks! I was starting to go a little crazy -- didn't even think about this. Commented Feb 23, 2015 at 5:40
-
What is the "some_element"?Is the ID of the element?How can I find this?– DionCommented May 27, 2015 at 9:01
-
@sokratis you can get the IDs of elements by dpm($form), they appear in the first level of $form array. The following is an actual example of altering comment form: <code> function MYMODULE_form_alter(&$form, &$form_state, $form_id) { if ($form_id == 'comment_node_post_form') { $form['subject']['#attributes']['placeholder'] = t('Subject'); $form['comment_body']['und'][0]['value']['#attributes']['placeholder'] = t('Content'); } }</code>– HenryCommented Sep 14, 2015 at 23:25
Stumbled upon this and thought Clive's answer seemed nice to automatically add placeholders.
Thou, a few minor changes are needed to get it right in drupal 8, so here's pretty much the same answer, but suitable for your drupal 8 theme.
/**
* Implements hook_form_alter
*/
function THEME_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
add_placeholders($form);
}
/**
* Add placeholders to suitable form elements -> textfield, password, email, textarea
*/
function add_placeholders(&$element) {
if(isset($element['#type']) && in_array($element['#type'], ['textfield', 'password', 'email', 'textarea'])) {
$element['#attributes']['placeholder'] = $element['#title'];
}
foreach(\Drupal\Core\Render\Element::children($element) as $key) {
add_placeholders($element[$key]);
}
}
-
Thank you, works great! But should be mentioned, that this solution just works for forms without fieldsets, so this may need some recursive loop for nested fields.– ThomasCommented Jun 8, 2020 at 16:12
Simply add the code for placeholder text
/**
* Implements hook_form_alter
*/
function MODULENAME_form_alter(&$form, \Drupal\Core\Form\FormStateInterface
$form_state, $form_id) {
form['field_YOURFIELDNAME']['widget'][0]['value']['#placeholder'] = t('Some text');
}
I've found this solution here that worked for me:
/**
* Implements template_preprocess_input().
*/
function MYTHEME_preprocess_input(&$variables) {
// Set a placeholder for all search form elements.
if ($variables['attributes']['type'] == 'search') {
$variables['attributes']['placeholder'] = $variables['element']['#title'];
}
}
If you want to target a form instance directly use hook_form_FORM_ID_alter. Might be tidier than using conditionals. My solution for targeting the search form block instance only.
function eyecare_form_search_block_form_alter(&$form, $form_state) {
$form['keys']['#attributes']['placeholder'] = t('Search');
}