Download & Extend

Having the form hook_form() causes issues

Project:AHAH helper
Version:6.x-2.0
Component:Code
Category:support request
Priority:normal
Assigned:Rok Žlender
Status:postponed (maintainer needs more info)

Issue Summary

I used the example that came with the ahah_helper_demo.

When I place the form in the hook_form function and I run it, it doesn't work correctly. It loads with the default company fields as the default option is "Company" however when I select "Private" and the form reloads, it does not display the private fields but instead displays the company fields.

I modified the module to have the form in the hook_form_alter instead and it seems to work. My question is, is there a specific reason why I need to have the form in the hook_form_alter instead of the hook_form?

I have the code below, the first example is having the form in the hook_form() and the 2nd example (the one that works) I have the form in the hook_form_alter().

Thanks!

Version that does not work.

<?php
function testmodule_node_info()
{
    return array(
       
'testmodule' => array(
           
'name' => t('testmodule'),
           
'module' => 'testmodule',
           
'description' => t('Node for testing'),
           
'has_title' => TRUE,
           
'title_label' => t('Title'),
           
'has_body' => TRUE,
           
'body_label' => t('Description'),
           
'min_word_count' => 0,
           
'locked' => TRUE
           
)
        );
}

function
testmodule_menu()
{  
 
$items['testmodule'] = array(
   
'page callback'    => 'drupal_get_form',
   
'page arguments'   => array('testmodule_form'),
   
'access callback'  => TRUE,
   
'type'             => MENU_CALLBACK,
  );
 
   

    return
$items;
}
function
testmodule_form_alter(&$form, &$form_state, $form_id)
{
    if (
$form_id =='testmodule_node_form')
    {    
       
ahah_helper_register($form, $form_state); 
    }  
}

/**
* Implementation of hook_form().
*/
function testmodule_form($node)
{
    if (!isset(
$form_state['storage']['billing_info']['usage']))
    {
       
$usage_default_value = 'company';
    }
    else
    {
       
$usage_default_value $form_state['storage']['billing_info']['usage'];
    }

   
$form['billing_info'] = array(
       
'#type'   => 'fieldset',
       
'#title'  => t('Billing information'),
       
'#prefix' => '<div id="billing-info-wrapper">', // This is our wrapper div.
       
'#suffix' => '</div>',
       
'#tree'   => TRUE, // Don't forget to set #tree!
   
);
   
   
$form['billing_info']['usage'] = array(
       
'#type' => 'select',
       
'#title' => t('Usage'),
       
'#options' => array(
         
'private' => t('Private'),
         
'company' => t('Company'),
        ),
       
'#default_value' => $usage_default_value,
       
'#ahah' => array(
             
'event'   => 'change',
             
// This is the "magical path". Note that the parameter is an array of
              // the parents of the form item of the wrapper div!
             
'path'    => ahah_helper_path(array('billing_info')),
             
'wrapper' => 'billing-info-wrapper',
        ),
    );
   
$form['billing_info']['update_usage'] = array(
       
'#type'  => 'submit',
       
'#value' => t('Update usage'),
       
// Note that we can simply use the generic submit callback provided by the
        // ahah_helper module here!
        // All it does, is set $form_state['rebuild'] = TRUE.
       
'#submit' => array('ahah_helper_generic_submit'),
       
// We set the 'no-js' class, which means this submit button will be hidden
        // automatically by Drupal if JS is enabled.
       
'#attributes' => array('class' => 'no-js'),
    );
   
   
   
// If 'company' is selected, then these two form items will be displayed.
   
if ($usage_default_value == 'company')
    {
       
$form['billing_info']['company_name'] = array(
         
'#type'      => 'textfield',
         
'#title'     => t('Company name'),
         
'#required'  => TRUE,
         
'#size'      => 20,
         
'#maxlength' => 255,
         
// If the user switched to Private usage and back to Company usage, we
          // remembered his company's name!
         
'#default_value' => $form_state['storage']['billing_info']['company_name'],
        );
       
$form['billing_info']['vat'] = array(
         
'#type'        => 'textfield',
         
'#title'       => t('VAT number'),
         
'#description' => t('Please enter a Belgian VAT number, the format is: <em>BE0999999999</em>.'),
         
'#size'        => 20,
         
'#maxlength'   => 255,
         
// If the user switched to Private usage and back to Company usage, we
          // remembered his VAT number!
         
'#default_value' => $form_state['storage']['billing_info']['vat'],
         
'#ahah' => array(
           
'event' => 'blur',
           
'path' => ahah_helper_path(array('billing_info', 'vat')),
           
'wrapper' => 'edit-billing-info-vat-wrapper',
           
'effect' => 'none',
           
'method' => 'replace',
          ),
        );
       
// Provide instantaneous (#ahah-powered) feedback to the user about the
        // VAT number he entered.
       
if (isset($form_state['storage']['billing_info']['vat']) && strlen($form_state['storage']['billing_info']['vat']) > 0)
        {
           
$form['billing_info']['vat']['#field_suffix'] = theme('image', (preg_match('/^BE0\d{9}$/', $form_state['storage']['billing_info']['vat'])) ? 'misc/watchdog-ok.png' : 'misc/watchdog-error.png');
        }
    }
   
// And if 'private' is selected, then these two form items will be displayed.
   
else
    {
       
$form['billing_info']['first_name'] = array(
         
'#type'      => 'textfield',
         
'#title'     => t('First name'),
         
'#required'  => TRUE,
         
'#size'      => 20,
         
'#maxlength' => 255,
         
// If the user switched to Company usage and back to Private usage, we
          // remembered his first name!
         
'#default_value' => $form_state['storage']['billing_info']['first_name'],
        );
       
$form['billing_info']['last_name'] = array(
         
'#type'      => 'textfield',
         
'#title'     => t('Last name'),
         
'#required'  => TRUE,
         
'#size'      => 20,
         
'#maxlength' => 255,
         
// If the user switched to Company usage and back to Private usage, we
          // remembered his last name!
         
'#default_value' => $form_state['storage']['billing_info']['last_name'],
        );
    }
   
   
$form['billing_info']['address'] = array(
       
'#type'      => 'textfield',
       
'#title'     => t('Address'),
       
'#required'  => TRUE,
       
'#size'      => 20,
       
'#maxlength' => 255,
       
// Always set #default_value, even if it's not a dynamically added form item!
       
'#default_value' => $form_state['storage']['billing_info']['address'],
    );
   
$form['billing_info']['country'] = array(
       
'#type'      => 'textfield',
       
'#title'     => t('Country'),
       
'#size'      => 20,
       
'#maxlength' => 255,
       
// Always set #default_value, even if it's not a dynamically added form item!
       
'#default_value' => $form_state['storage']['billing_info']['country'],
    );
   
   
$form['save'] = array(
       
'#type'  => 'submit',
       
'#value' => t('Save'),
    );
 
    return
$form;
}
?>

Version that works.

<?php
function testmodule_node_info()
{
    return array(
       
'testmodule' => array(
           
'name' => t('testmodule'),
           
'module' => 'testmodule',
           
'description' => t('Node for testing'),
           
'has_title' => TRUE,
           
'title_label' => t('Title'),
           
'has_body' => TRUE,
           
'body_label' => t('Description'),
           
'min_word_count' => 0,
           
'locked' => TRUE
           
)
        );
}

function
testmodule_form_alter(&$form, &$form_state, $form_id)
{
    if (
$form_id =='testmodule_node_form')
    {    
       
ahah_helper_register($form, $form_state); 
       
       
testmodule_theform(&$form, $form_state);
    }  
}

function
testmodule_theform(&$form, $form_state)
{
    if (!isset(
$form_state['storage']['billing_info']['usage']))
    {
       
$usage_default_value = 'company';
    }
    else
    {
       
$usage_default_value $form_state['storage']['billing_info']['usage'];
    }

   
$form['billing_info'] = array(
       
'#type'   => 'fieldset',
       
'#title'  => t('Billing information'),
       
'#prefix' => '<div id="billing-info-wrapper">', // This is our wrapper div.
       
'#suffix' => '</div>',
       
'#tree'   => TRUE, // Don't forget to set #tree!
   
);
   
   
$form['billing_info']['usage'] = array(
       
'#type' => 'select',
       
'#title' => t('Usage'),
       
'#options' => array(
         
'private' => t('Private'),
         
'company' => t('Company'),
        ),
       
'#default_value' => $usage_default_value,
       
'#ahah' => array(
             
'event'   => 'change',
             
// This is the "magical path". Note that the parameter is an array of
              // the parents of the form item of the wrapper div!
             
'path'    => ahah_helper_path(array('billing_info')),
             
'wrapper' => 'billing-info-wrapper',
        ),
    );
   
$form['billing_info']['update_usage'] = array(
       
'#type'  => 'submit',
       
'#value' => t('Update usage'),
       
// Note that we can simply use the generic submit callback provided by the
        // ahah_helper module here!
        // All it does, is set $form_state['rebuild'] = TRUE.
       
'#submit' => array('ahah_helper_generic_submit'),
       
// We set the 'no-js' class, which means this submit button will be hidden
        // automatically by Drupal if JS is enabled.
       
'#attributes' => array('class' => 'no-js'),
    );
   
   
   
// If 'company' is selected, then these two form items will be displayed.
   
if ($usage_default_value == 'company')
    {
       
$form['billing_info']['company_name'] = array(
         
'#type'      => 'textfield',
         
'#title'     => t('Company name'),
         
'#required'  => TRUE,
         
'#size'      => 20,
         
'#maxlength' => 255,
         
// If the user switched to Private usage and back to Company usage, we
          // remembered his company's name!
         
'#default_value' => $form_state['storage']['billing_info']['company_name'],
        );
       
$form['billing_info']['vat'] = array(
         
'#type'        => 'textfield',
         
'#title'       => t('VAT number'),
         
'#description' => t('Please enter a Belgian VAT number, the format is: <em>BE0999999999</em>.'),
         
'#size'        => 20,
         
'#maxlength'   => 255,
         
// If the user switched to Private usage and back to Company usage, we
          // remembered his VAT number!
         
'#default_value' => $form_state['storage']['billing_info']['vat'],
         
'#ahah' => array(
           
'event' => 'blur',
           
'path' => ahah_helper_path(array('billing_info', 'vat')),
           
'wrapper' => 'edit-billing-info-vat-wrapper',
           
'effect' => 'none',
           
'method' => 'replace',
          ),
        );
       
// Provide instantaneous (#ahah-powered) feedback to the user about the
        // VAT number he entered.
       
if (isset($form_state['storage']['billing_info']['vat']) && strlen($form_state['storage']['billing_info']['vat']) > 0)
        {
           
$form['billing_info']['vat']['#field_suffix'] = theme('image', (preg_match('/^BE0\d{9}$/', $form_state['storage']['billing_info']['vat'])) ? 'misc/watchdog-ok.png' : 'misc/watchdog-error.png');
        }
    }
   
// And if 'private' is selected, then these two form items will be displayed.
   
else
    {
       
$form['billing_info']['first_name'] = array(
         
'#type'      => 'textfield',
         
'#title'     => t('First name'),
         
'#required'  => TRUE,
         
'#size'      => 20,
         
'#maxlength' => 255,
         
// If the user switched to Company usage and back to Private usage, we
          // remembered his first name!
         
'#default_value' => $form_state['storage']['billing_info']['first_name'],
        );
       
$form['billing_info']['last_name'] = array(
         
'#type'      => 'textfield',
         
'#title'     => t('Last name'),
         
'#required'  => TRUE,
         
'#size'      => 20,
         
'#maxlength' => 255,
         
// If the user switched to Company usage and back to Private usage, we
          // remembered his last name!
         
'#default_value' => $form_state['storage']['billing_info']['last_name'],
        );
    }
   
   
$form['billing_info']['address'] = array(
       
'#type'      => 'textfield',
       
'#title'     => t('Address'),
       
'#required'  => TRUE,
       
'#size'      => 20,
       
'#maxlength' => 255,
       
// Always set #default_value, even if it's not a dynamically added form item!
       
'#default_value' => $form_state['storage']['billing_info']['address'],
    );
   
$form['billing_info']['country'] = array(
       
'#type'      => 'textfield',
       
'#title'     => t('Country'),
       
'#size'      => 20,
       
'#maxlength' => 255,
       
// Always set #default_value, even if it's not a dynamically added form item!
       
'#default_value' => $form_state['storage']['billing_info']['country'],
    );
}
?>

Comments

#1

Thanks for the code buddy! I was stucked in the very same place and kept banging my head to the desk. Otherwise ahah_helper is just wonderfull. Just poor Wim doesn't have much time to document it properly. I think if it does it can make it quickly to the core.

#2

Good Work!

#3

Try putting these two lines at the top of your hook_form functions

<?php
  $form
= array();
 
ahah_helper_register($form, $form_state);
?>

also you should change hook_form function definition to comply with http://api.drupal.org/api/function/hook_form/6 . I haven't tried it but I think it should work.

#4

Assigned to:Anonymous» Rok Žlender
Status:active» postponed (maintainer needs more info)

#5

Ah, sorry please ignore this post.
I added it in the wrong place...

#6

#7

I posted an alternative solution to this problem here http://drupal.org/node/328201#comment-4434040

nobody click here