Goal:

ADD(or or modify) an attribute of a form field.
For this example, we'll be ADDING the "size" attribute to a multi select box in a custom content type, with the intent to make the select box bigger, vertically, so that more options are visible at once.

What you'll need to know:

  1. How to create and enable a custom module (not covered here)
  2. my_form_id (The form ID of the form you want to change, see previous page for details)
  3. my_field_name (The field name of the form field you want to modify, see section below for details)
  4. my_content_type (The content type you're changing the fields for. Don't worry if you're not dealing with a content type form, the below info applies to just about any form you'll likely come across).

The resulting code:

/**
 * Implements hook_form_alter().
 */
function mymodule_form_alter(&$form, $form_state, $form_id) {
  if($form_id == 'my_form_id'){
    $form['my_field_name']['#language']['#size'] = '20';
  }
}

The What, Where, and Why:

if($form_id == 'my_form_id')
This IF statement is important if you you do not want to process every form on your site with this modification.
*note - If someone could verify any potential performance issues with leaving the if-statement out, please do!

$form['my_field_name']['#language']['#size'] = '20';
What we're looking at here is the manner in which we'll be making our modification to the form field.
$form['my_field_name'] tells the system which field we want to modify.

Identifying the field name:

Browse to: admin/structure/types/manage/my_content_type/fields and take a look in the "NAME" column for the field name of the field you want to modify. That is your "my_field_name".

If I don't know where to get the "my_field_name" from, or am working with a field in a form that doesn't give us such a clean way to get this information (i.e. someone else's module), I like to use the function "drupal_set_message" as a quick and dirty way to dump variables for quick viewing while working on this type of issue.
For example, adding the following code to your hook_form_alter() will make a message box pop up (wherever your particular theme's message boxes pop up) containing the words "Hello World!" (don't forget to remove or at least comment this out when you're done with it!):
drupal_set_message('Hello World');

For our purposes, we'll use this to find out what "my_field_name" is. The following line will show you ALL of the fields in the form, along with a ton of extra data you may not need at the moment (or ever), but it's a quick and dirty way to get your hands on the data you need right now, laid out in a way that should be fairly legible (hence the PRE tags).
Just add the following line to your hook_form_alter() function (don't forget to remove or at least comment this out when you're done with it!):
drupal_set_message('<pre>' . print_r($form, true) . '</pre>');

The Language Barrier:

The next section of our $form[field_name] modifying statement looks like this:
$form['my_field_name']['#language']
If you look through the output from the drupal_set_message function's output above, you'll see that there is a "[#language] = und" setting for the field (my D7 site doesn't even have multi-lingual settings, and it was there, but YMMV). You'll probably see under that "[und] => Array" (without the hashtag). By using "$form['my_field_name']['#language'] in place of [und], we can be a little more certain that if we're working with a multi-lingual site, this modification will still work (not tested! YMMV)!

Hook, line and sinker:

With that out of the way, our final segment of the $form[field_name] modifying statement looks like this:
['#size'] = '20';

This will ADD the #size attribute to our select box, and set it to show 20 lines of options (or, on a select-with-grouping select list, both options and optgroups).

Comments

SomebodySysop’s picture

The field name is 'og_group_ref'. When I print out the form, I find it several times in this format:

[og_group_ref] => Array
                                        (
                                            [und] => Array
                                                (
                                                    [0] => Array
                                                        (
                                                            [target_id] => 4
                                                        )

                                                )

                                        )

All I want to do is select a default value? How would I do that? My guess was something like:

$form['og_group_ref']['und'][0]['target_id']  = 6; // 6 is the gid of the group I want to automatically select.

Thanks!
But, of course, that didn't work. Any suggestions?

mudasirweb’s picture

Hi Did u got this sought out, I got stuck in the same situation,

["og_group_ref"]=>
    array(1) {
      ["und"]=>
      array(1) {
        [0]=>
        array(1) {
          ["target_id"]=>
          string(3) "101"
        }
      }
    }

Even I tried to print the value using this, its not working.

$element = $form->node['og_group_ref']['und'][0]['target_id']
var_dump($element);
dskanth’s picture

I used the hook_form_FORM_ID_alter to alter the submit action URL for the node creation form, of a particular content type.

$form['actions']['submit']['#submit'][0] = 'add_mymodule_content';

So now i can track all the individual form values in my module function, add_mymodule_content() and control what is being inserted in the database. It is really cool.

wheelercreek’s picture

Just FYI - this:

$form['my_field_name']['und']['#size'] = '20';

works. But this:

$form['my_field_name']['#language']['#size'] = '20';

Doesn't work, as $form['my_field_name']['#language'] is a string, not an array. The best (and proper) solution would be this:

$form['my_field_name'][$form['my_field_name']['#language']]['#size'] = '20';

It's pretty ugly, but will work for multi-language sites or undeclared (und) language sites (the default).

In the past, another way I had solved this was to create a clone of the Drupal Seven theme, and then use that as my admin theme, and modify the CSS. This is much better.