Fragmented Thought

Using HTML 5 Inputs in Drupal 7 Through Theming



Lance Gliser

Heads up! This content is more than six months old. Take some time to verify everything still works as expected.

I'm putting together a feedback form for a client today in Drupal. I've been experimenting with ways to improve the form's efficiency, just general UX. One of the sticking points for me was the complete lack of simple support for HTML 5 input types in Drupal 7. Thankfully this is fixed in Drupal 8. For those of us needing to work today, here's an easy solution.

The most 'helpful' solution I found before going rogue was on stack overflow. Except it really doesn't work as advertised, and even if it did, you add a module dependency. No dice. First, understand that Drupal itself is pretty stuck on its item types. You could introduce a new type, but it's quite a bit of work, and you run the risk of module conflicts. It's far safer to simply use the theming layer to handle your one off requirements as they come up. If you're using this a lot, it might not be the best solution, but it is fast.

Start with your standard form callback, and add a #theme property to your field.

/** * @param $form * @param $form_state * @return array */ function custom_form($form, &$form_state){ ... $form['email'] = array( '#type' => 'textfield', '#title' => t('Email'), '#required' => TRUE, '#attributes' => array( 'placeholder' => t('Enter your email.'), ), '#theme' => 'custom_email_input' // This will route to our customization below ); ... return $form; }

Implement hook theme in custom.module:

/** * Implements hook_theme */ function pw_feedback_theme(){ return array( 'custom_email_input' => array( 'render element' => 'element', 'file' => '', ), ); }

Implement the theme callback in

/** * Returns HTML for a textfield form element of type email. * * @param $variables * An associative array containing: * - element: An associative array containing the properties of the element. * Properties used: #title, #value, #description, #size, #maxlength, * #required, #attributes, #autocomplete_path. * * @ingroup themeable * @see theme_textfield */ function theme_custom_email_input($variables){ // Force the core handling of the element $output = theme_textfield($variables); // Upgrade to the email type $output = str_replace('type="text"', 'type="email"', $output); return $output; }

This won't give you the upgraded validation automatically. It's easy to add that, but not in the scope of this little post. Check out the #element_validate property for details.