Extreme Form Handling in Drupal

Posted May 12, 2008 Posted // 6 comments
Irakli:

Drupal Form-Handling support goes far beyond just the documented part of so-called Forms API. You can do pretty much anything with forms in Drupal and you can use/display the forms anywhere. Here is an example. Let’s assume we want to construct a custom node type with custom fields, using CCK. Then we want to display this form into some non-standard page. To further complicate things, let’s assume we also want custom verification and processing routines. And last but not least – we want to use full power of Drupal and write a minimal amount of code.Drupal Form-Handling support goes far beyond just the documented part of so-called Forms API. You can do pretty much anything with forms in Drupal

and you can use/display the forms anywhere.

Here is an example. Let’s assume we want to construct a custom node type with custom fields, using CCK. Then we want to display this form into some non-standard page. To further complicate things, let’s assume we also want custom verification and processing routines.

And last but not least – we want to use full power of Drupal and write a minimal amount of code. Following is a snippet demonstrating key points to achieving this task (thorough understanding of Drupal is required):


$node = new StdClass();
$node->type = OUR_NODE_TYPE;

$form = node_form ( $node ) ;
drupal_prepare_form( OUR_NODE_FORM_ID, $form ); //Let all form hooks run

//— Indicate proper processor, submit function, validate function etc.
$form['#action'] = '/node/add/'.OUR_NODE_TYPE;
$form['#validate'] = array('ourmodule_ourvalidationfunc' => array());
$form['#submit'] = array('ourmodule_oursubmitfunc' => array());

ourmodule_form_disable_defaults( $form );

//— Render the form:
$form_html = drupal_render_form( OUR_NODE_FORM_ID, $form );

//— You just got a rendered HTML of the form in $form_html that you can
//— add to your output
.....

/**
* Disable some annoying default fields just for the
* kicks and to demo the power  of what can be done.
*/
function ourmodule_form_disable_defaults ( &$form ) {

      $form['attachments']['#collapsed'] = 0;
      $form['body_filter']['format'] = null;
      $form['format'] = array('#type' => 'hidden',
                              '#value' => 1);
      $form['log'] = null;
      $form['log'] = array('#type' => 'hidden',
                           '#value' => '');

      $form['comment_settings'] = null;
        $form['comment'] = array('#type' => 'hidden',
                                 '#value' => 2);
      $form['menu'] = null;
    
      $form['body_filter']['body']['#rows'] = "5";

      $authorname = $user->name;
        $form['author'] = null;
        $form['name'] = array('#type' => 'hidden',
                              '#value' => $authorname);
      $form['options'] = null;
      $form['path'] = null;
      $form['status'] = array('#type' => 'hidden',
                              '#value' => 1);
                            
      $form['preview']=null;

}

Please note that if your machine-readable name of the custom node type is something like “flight_schedule” then you will be defining the constants used in the code, as follows:


define ('OUR_NODE_TYPE', 'flight_schedule');
define ('OUR_NODE_FORM_ID', 'flight_schedule_node_form');

Also, both the custom validation and submit functions have similar signature:


function ourmodule_ourvalidationfunc ($form_id, $form_values)
// and
function ourmodule_oursubmitfunc ($form_id, $form_values)

where $form_id is the Drupal form_id of the form and $form_values is an indexed array of submitted values. In the validation function you can set alert points using form_set_error() function like this:


form_set_error('field_flight_schedule', t('Flight Schedule ID must be unique.'));

where field_flight_schedule is a form element ID coming from a CCK field.

Also, for node forms you can call the original submit function from your submit function, so that you don’t have to duplicate things it already does. You do it with something like:

$original_return = node_form_submit($form_id, $form_values);

and you can end your _submit function with “return $original_return” so form submit redirects to where it would normally do.

The rest of the code should be self-explanatory, given a reader is proficient in Drupal. Also, you can leave comments here, if you have further questions.

About Irakli

Irakli is Director of Product Development at Phase2 Technology. His main responsibility is development of packaged, turn-key solutions using open-source technologies and cutting-edge semantic APIs.

Irakli has been an avid open-source ...

more >

Read Irakli's Blog

Comments

by matslats (not verified) on Wed, 05/14/2008 - 03:44

context

Irakli, thanks for writing this, it’s just exactly the area I’m stuck on. Can you say a bit more about where to write this code, given that the contentType is defined in CCK. Do you write a module as well? So how do you link the module to to the CCK type? This is relevant here:
http://www.civicactions.com/blog/cck_import_and_update

Also perhaps you could say something about producing a confirmation page for a CCK add/node operation?
Matthew

by irakli on Wed, 05/14/2008 - 11:43

CCK Import During Install

Matt,

yes, you should create a module and put such code into that module. In the .install file of that module you can import CCK definition with a code like:

function ourmodule_CCK_install() {

$modulepath = drupal_get_path ('module', 'ourmodule');
$cck_definition_file = $modulepath."/custom.cck";

  $values['type_name'] = '<create>';
  $values['macro'] = file_get_contents($cck_definition_file);
 
  include_once( drupal_get_path('module', 'node') .'/content_types.inc');
  include_once( drupal_get_path('module', 'content') .'/content_admin.inc');
 
  drupal_execute("content_copy_import_form", $values);
}

where custom.cck under your module folder is the file that you can export from CCK if you have cck_content_copy module installed.

by Avangelist (not verified) on Mon, 11/17/2008 - 09:50

yeah I have to say

so far I have found that the webform module is a bit of a bust, it is great to be able to quickly build these forms and everything but it is completely useless if you cannot provide your own action for it.

by pupster (not verified) on Fri, 07/04/2008 - 17:50

easier way

wow, i wish there was an easier way. i’m proficient in drupal, but not APIs.
I’m looking to provide a feedback form that includes a specific subject line and ID. so the usr clicks on a node, the node has a unique id, and when the user clicks “email” or “contact,” the node ID is sent with the email.

by irakli on Fri, 07/04/2008 - 20:53

WebForm Module

For something like that you do not need to write code. Take a look at the WebForm module: [ http://drupal.org/project/webform ]

by stinky (not verified) on Sun, 07/13/2008 - 14:28

webform won't work

Webforms won’t really work for what i’m doing. If I have 50 listings I’d have to create a web form for each listing.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
  • Allowed HTML tags: <a> <strong> <code> <p> <img> <ul> <ol> <li> <h2> <h3> <h4> <b> <u> <i>

More information about formatting options