11

Is there a way to add or change a class to a form wrapper (the div's) using the form api?

Or is that just done with the theme function ?

If so which theme function is used to change that?

  • I'm pretty sure that's a theme function. Which theme function to use is the question. :) – akalata Sep 14 '11 at 0:57
  • Ah you're right there. – chrisjlee Sep 14 '11 at 1:25
  • I think you can also use the #attribute key to define a class – Mika A. Sep 14 '11 at 7:25
  • @Mika A. This only applies to the <input> tag i'd like to change the class of the wrapper (a <div>). – chrisjlee Sep 14 '11 at 18:28
5

You can override theme_form_element() normally if you want to change the theming globally. If you're interested in modifying just one specific form element then I'm aware of a couple of choices.

  1. You can register a new theme function for the particular type of form element you're interested in (eg. textfield). You then create this theme function (based on the original, eg. theme_textfield()) but that doesn't call theme('form_element', ...) at the end (you could either handle both the wrapper and the element in the one theme function, or you could make a separate wrapper theme function and use that). Finally you add a #theme property to a particular form element, and that element will get your custom theming.

  2. You can create a template file called form_element.tpl.php which just has the default behaviour of theme_form_element() and then use hook_preprocess_form_element() to add a template suggestion. Then you create the new template that matches the suggestion. You often hear people mentioning that templates are slightly slower than functions, and for such a frequently used theme call I can imagine people balking at using a template. I've never done any measurements for this myself however. Also, you need to have enough context at the preprocess stage to be able to make the suggestion.

  • Could you provide an example? – chrisjlee Jan 27 '12 at 21:01
  • @ChrisJ.Lee Do you want to change the wrapper on all elements, or just one particular one? – Andy Jan 28 '12 at 13:07
  • just a single one. – chrisjlee Feb 1 '12 at 3:23
  • @chrisjlee I've updated the answer. – Andy Feb 1 '12 at 13:47
3

I know this is a super old thread, but I'v been learning how to alter form elements and add classes. I got around to making a custom module:

function yourtheme_custom_form_alter(&$form, &$form_state, $form_id) {
 case'webform_number_whatever':
   _yourtheme_form_add_wrapper($form['submitted']['yourfieldhere'], array('form-field-some-style', 'not-label', 'whatever-other-styles-you-want'));
 break;
}

function _yourtheme_form_add_wrapper(&$element, $classes = array(), $type = array('form-item', 'form-type-textfield'), $removeTitle = FALSE){
  $element['#prefix'] = '<div class="' . implode(" ", $classes) . '"><div class="' . implode(" ", $type) . '">';
  $element['#suffix'] = '</div></div>';
}
  • This is a good alternative solution - don't add a class to the wrapping div, just wrapping the wrapping div in your own div and they you can apply whatever classes you want. – Felix Eve Feb 11 '14 at 15:10
3

To Change the "wrapper" you need to override form_element. Basically all form elements get rendered with the form_element theme theme_form_element($element,$value); (form.inc file)

So to change how this renders your form elements you simply copy that function to your template.php folder and rename it to: phptemplate_form_element($element,$value)

now you can make any changes and they will be used instead of the original function

  1. Copy theme_form_element($element,$value); from form.inc
  2. Paste it into (your theme) template.php
  3. rename it to: phptemplate_form_element($element,$value)
  4. clear all theme cache
  5. make whatever changes you want and they will be used.
0

Importantly, theme_form_element will only modify the direct parent wrapper div and this may not be the intended target for CSS effects.

[Although not programmatic, if one simply wants to apply a class to a node field's top-wrapper (it's wrapper's, wrapper's, wrapper) one can I suppose use "Field group" module by selecting "Manage Fields" for a particular content type and select "Add new group" as a simple DIV. Then the label can be removed and desired classes assigned to the additional wrapper (but now we have even more wrappers) - with unlimited nesting]

0

You could use

'#prefix' => '<div class="new_class">', '#suffix' => '</div>'

and this will wrap it around

0

Make wrapper attributes configurable!

Create your own form-element theme function in your theme... sites/all/themes/MY_THEME/theme/form-element.theme.inc

function my_theme_form_element($variables) {
  $element = &$variables['element'];

  $attributes = isset($element['#my_theme_wrapper_attributes']) ?
    $element['#my_theme_wrapper_attributes'] : array();

  ...

  $output = '<div' . drupal_attributes($attributes) . '>' . "\n";

  ...
}

Then you can do stuff like this...

function my_module_form_alter(&$form, &$form_state, $form_id) {
  $form['account']['mail']['#my_theme_wrapper_attributes']['class'][] = 'form-field--inline';
}
0

There are come cases in which neither #prefix/#suffix nor #attributes => array('class') give the desired results. My particular case is adding a class to the ajax-wrapper div around a managed_file element. #prefix/#suffix creates a new container and #attributes/'class' modifies the class of an inner element, not the outermost.

The normal outermost div is just

<div id="edit-doc1--XX-ajax-wrapper">

which is difficult to target in CSS. I can target [id^="edit-doc"] or [id$="-ajax-wrapper"] but both of these target more than just the elements I wanted.

The solution I came up with is to add a #process element to the form and manually manipulate the element's code. Here's the #process attribute added to the form item's declaration:

$form['doc1'] = array(
  '#type' => 'managed_file',
  '#process' => array('mymodule_managed_file_process'),
);

And here's the mymodule_managed_file_process() function:

function mymodule_managed_file_process($element, &$form_state, $form) {

  // Call the original function to perform its processing.
  $element = file_managed_file_process($element, $form_state, $form);

  // Add our own class for theming.
  $element['#prefix'] = str_replace(
    'id=',
    'class="managed-file-wrapper" id=',
    $element['#prefix']
  );

  return $element;
}

Relying on string substitution isn't very portable, so use str_replace at your own risk. This code, however, does indeed alter the outermost DIV to add the necessary class:

<div class="managed-file-wrapper" id="edit-doc1--XX-ajax-wrapper">
-1
<?php
    $form['#attributes'] = array('class' => 'your-class-name');
?> 

You can use the above way to add a class on the form element.

  • 6
    How would you then modify the class of the div? The above code changes the class of the <input /> tag. – chrisjlee Sep 14 '11 at 18:28
  • 1
    This answer is wrong for the specific question asked here. – doublejosh Mar 18 '16 at 0:15

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.