I’m having difficulty understanding Form API. I’ve read several posts, including handbooks, but I’m never certain exactly what it is people are excited about and just what exactly they are creating and/or altering. Some say they’re creating pages with PHP input, others say there making original PHP files, and yet others say they’re writing modules?!

Would it be possible to explain in rather simple terms A. what is created, B. what it’s named, and C. where it’s placed?

Create
If you want to make a form (i.e name, address, email), then do A, B, and C.

Alter
If you want to remove or add a form element (i.e. a collapsed field) from an existing form (i.e. create page), then do A, B, and C.

I apologize if the answers to these questions are painfully obvious to you.

Comments

pwolanin’s picture

...so don't feel any chagrin about your initial confusion.

Have you looked at the resouces on http://api.drupal.org? In particular, start with this guide: http://api.drupal.org/api/4.7/file/developer/topics/forms_api.html

One of the useful things about he Forms API is that it defines an abstract representation of a form and then allows modules to alter the form before it is actually turned into HTML. This is frequently used in core- for example, to add the taxonomy selector to the node submssion form. It can also be handy for tweaking the behavior of Drupal's core modules- see, for example: http://drupal.org/node/70906

---
Work: BioRAFT

nedjo’s picture

Create
If you want to make a form (i.e name, address, email), then do A, B, and C.

In a module (a file with a .module extension):

A. Write a function that creates a form:

function examplemodule_example_form() {
  // The form is an array. It doesn't need to have any direct properties.
  $form = array();
  // Each 'element' on the form (which can be a field) is an element in the form array. This first one we'll give the name 'title'.
  $form['title'] = array(
    // We give the form element a series of properties, which are keys to the element's array and have names starting with '#'.
    // One property is the type, which controls how the form element will be 'rendered' (output as HTML).
    '#type' => 'textfield',
    // We can give various other properties.
    '#title' => t('The title of your article'),
  );
  return $form;
}

B. Return and render the form in a function:


function examplemodule_example_page()  {
  $form = examplemodule_example_form();
  // The first argument becomes the 'form_id' of your form.
  $output = drupal_get_form('examplemodule_example_form', $form);
  return $output; 
}

C. Do something with the input of your form:

When someone fills out your form, Drupal will look for a function named [form_id]_submit.


function exampleform_example_form_submit($form_id, $form_values) {
  // E.g., do an SQL insert based on the $form_values['title'].
}

If you want to remove or add a form element (i.e. a collapsed field) from an existing form (i.e. create page), then do A, B, and C.

A. In your module, include a function called modulename_form_alter.


function examplemodule_form_alter($form_id, &$form) {
  // Look for the form you want to alter, by id:
  if ($form_id == 'othermodule_form') {
    // Add new form elements, or, as in this case, change existing ones. Because $form is passed 'by reference', changes you make here will be made to the form.
    $form['title']['#description'] = t('Choose a descriptive title.');
  }
}

There's no B or C.

Look for examples in other modules of functions named like _form_alter.

nedjo’s picture

Prior to Forms API, a form was what a module author had hard-coded into a module. You couldn't change it--change existing field descriptions, reorder fields, add new fields. Now, through form_alter, you can. And, in 5.0, a fair bit more--e.g. programmatically submit form data (create and save an object without form submission).

syquest’s picture

After reading your comments, I assume the following. Please correct me if I am wrong

1. All this Form API stuff happen in existing modules - If I want to create or edit an existing form, I need to edit the appropriate .module file. (This also would mean no new files are created)

2. Form API is essentially altering the core, which I've been told several times is a very, very bad idea.

eaton’s picture

One of the reasons that FormAPI is necessary is *exactly* the situation you describe. If a form is defined as HTML, you DO have to hack the module that generates it. Under FormAPI, though, you would just write your OWN module that implements the hook_form_alter() hook. It gets a chance to change any elements of the form or insert its own elements while the form is still a set of nice, well-organized arrays.

--
Eaton's blog | VotingAPI discussion

--
Eaton — Partner at Autogram

syquest’s picture

So Form API is writting mini modules. So what I should first search for and learn about isn't necessarily Form API but how to write and implement modules?

syquest’s picture

O.K. with the code above I've created example.module, placed it in modules and enabled it in admin. But I don't see any options or forms anywhere. I must be missing something obvious.

How could this possible work with changing a core form like create page?

nedjo’s picture

You're not missing something obvious. You're missing something that takes some time and effort to learn.

The example code I gave you was not intended to be a fully operational module. It was intended rather to answer the questions you asked. It was not clear from your post that you had little or no experience coding with Drupal, and hence that you needed to be asking questions that were much more basic--and for which lots of documentation exists. If it had been clear, likely I would have answered differently.

To learn how to write a module, have a look at the handbook, http://drupal.org/node/508. Or study existing .module files. After you've done that, and put in some good effort on your own part, I suggest looking for support on the specific pieces that you don't understand. Please make an effort to make selective use of support forums. Answering broad questions that are already well documented elsewhere doesn't feel like a good use of my time, especially if the asker isn't able to use the answers I give.

In particular, look to hook_menu, where you provide access to a page. You need to create a page for your form to be displayed on.

syquest’s picture

Please accept my apologies if you think I’m not making good use of the forums and I'm wasting your time. I'll give the handbooks yet another try as you suggest. At least now I know that if I want to learn about altering forms I need to search for writing modules.

nedjo’s picture

And good luck with your form altering quest.

It's certainly true that the ability to alter forms is a nice idea for developers but not yet in the reach of average Drupal site administrators. 'All the excitement' has been in the developer community. Writing a custom module is a lot of work if all you want to do is e.g. add a #description to a form element, or change the order of some elements.

But I think good news is coming. A recent project, formbuilder.module, provides a user interface for building forms, http://drupal.org/project/formbuilder. (The code there requires some separate downloads.) While the original idea was building forms, the formbuilder code lends itself very well to altering existing forms as well. The author, Avi Mehta (silence on drupal.org), is working on extending his code so all site admins will have a friendly interface for making whatever changes they want to existing forms.

With any luck, in a couple of months the answer to your question will be, "Install formbuilder, and tweak to your heart's content."

droogie’s picture

Nedjo,

There has been no activity on formbuilder in over a year, that I can see. Is any of it stable enough to be used? Is there a demo?

davemybes’s picture

Nedjo, thanks for the dumbed-down explanation. I am busy trying to work my way through the Forms API and this clears up a few things for me. The API is definitely not simple, but a few lights are starting to come on for me :)

______________________________________________________________________________________________________

nedjo’s picture

1. Module implementing form (navigate to ?q=exampleform):


function exampleform_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'path' => 'exampleform',
      'callback' => 'exampleform_form',
      'title' => 'example form',
      'access' => user_access('access content'),
      'type' => MENU_CALLBACK
    );
  }
  return $items;
}

function exampleform_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      return t('Example of form construction.');
  }
}

function exampleform_form() {
  $form['parent'] = array(
    '#tree' => TRUE
  );
  $form['parent']['1'] = array(
    '#type' => 'textfield'
  );
  $form['submit']  = array(
    '#type' => 'submit',
    '#value' => t('Submit')
  );
  return drupal_get_form('exampleform_form', $form);
}

function exampleform_form_submit($form_id, $form_values) {
  foreach ($form_values['parent'] as $key => $value) {
    drupal_set_message(t('Value: %value', array('%value' => $value)));
  }
}

2. Module doing a sample form alter:


/**
 * @file
 * Sample of form altering.
 */

/**
 * Implementation of hook_help().
 */
function example_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      return t('Make a sample form alter.');
  }
}

/**
 * Implementation of hook_hform_alter().
 *
 * On node edit forms, alter the description of the title field.
 */
function example_form_alter($form_id, &$form) {
  // Match node editing forms. This function will affect all node editing forms but not any other form.
  // In general, you look for the 'form_id' of the form you want to alter. You can generally find it by
  // looking in the HTML source of the form as it's rendered on a page.
  // This test is taken from taxonomy_form_alter().
  if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
    // Set a description, referencing the node type.
    if (isset($form['title'])) {
      $form['title']['#description'] = t('Please describe your %type.', array('%type' => node_get_name($form['type']['#value'])));
    }
  }
}

davemybes’s picture

Wow, this is awesome. This example is worth its weight in gold. I always find that actual working examples are the best learning tools for me. I like to see how things work in a nice step-by-step manner so that I can trace changes to the code easily. I am now seeing more of the light with this API - the form_alter bit is incredible!

FYI, I am creating a form_alter module to change the user profile forms so that they won't all have the same sized fields among other things. When I have finished it, and everything works, I will create a post here to pass on the information to others. If you're all lucky, it will be done this week.

______________________________________________________________________________________________________

aryam8’s picture

Nedjo,
This is great!!! For the past couple of weeks i've been trying to understand how I can make good use of forms API and how to use existing custom created forms (with webforms). Your two exemples here just illustrate what I need to do. I want infact to use a form to get some parameters that will be used in a query and then create a .txt file with the results. I was needing a hybrid solution; creating a module that implements the _form_alter hook!

Thanks a million!

adrienf’s picture

Indeed, very interesting example, but what about Drupal 5.0?
I'm not able to run your (and others) example in it (no problem under Drupal 4.7.x).

I always got the following FireFox error: "The connection was reset". This error occurs on this line:

return drupal_get_form('exampleform_form', $form);

My config is:
- Windows XP
- easyphp 1.8 : apache 1.3.33 - php 4.3.10 - mysql 4.1.9 - phpmyadmin 2.6.1
- FireFox 2.0

Any Idea? I'm newbie in Drupal... have I did something wrong?

Thx in advance,
Adrien

pwolanin’s picture

see: http://drupal.org/node/64279#drupal-get-form

in 5.x, you don't pass $form.

---
Work: BioRAFT

awan’s picture

I am reallay sorry if asking this question at bad place.

Actually I have to put client side (javascript) validation in a form + I have to put some DHTML code (for displaying a radio button groupbox onClick of a checkbox).

Do you people have any idea how to do this ??

Where to put this code??

Any docs about this??

Any help will be appreciated..
Thanks a lot.

willi.firulais’s picture

Have you ever found your solution. I'm currently also in this situation.