Is there a way to convert a regular form and add placeholders with a module, or should this be done with a form template or with jQuery?

up vote 23 down vote accepted

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).

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. – Mike Crittenden Feb 23 '15 at 5:40
  • What is the "some_element"?Is the ID of the element?How can I find this? – sokratis May 27 '15 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> – Henry Sep 14 '15 at 23:25

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'),
      ),
    );
  • 1
    thx, this worked for me in Drupal 8. – No Sssweat Apr 19 '16 at 9:51

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]);
  }
}

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');
}

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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