Loading Form Definition Include Files in Drupal 7

This post was written 06/12/2015 and was migrated over from my Drupal 7 site, which is now offline.  Because of that, certain demonstrations in this post may not be functional.

Recently I had to include a form within an existing set of nodes (using hook_node_view), and this form had to make an AJAX callback. I put the form definition and Ajax callback function in a separate file for convenience. From my_ajax_test.module:

/**
* Implements hook_node_view().
*/
function my_ajax_test_node_view($node, $view_mode, $langcode) {
  //Conditional to ensure the form is only loaded on nodes that have
  //been flagged.
  if($node->flag == TRUE) {

    module_load_include('inc', 'my_ajax_test', 'my_ajax_test.forms');

    $new_form = drupal_get_form('my_ajax_test_node_form');

    $node->content['new_form'] = array(
         "#markup"=> drupal_render($new_form),
         "#weight"=> 100,
    );     
  }
}

The problem this caused was that the file with the form definition was not getting loaded on the Ajax callback, even though I use

module_load_include('inc', 'my_ajax_test', 'my_ajax_test.forms'); 

in the hook_node_view() function. The reason for this is that hook_node_view() is not processed during an Ajax callback. So what do you do to ensure that your form defintion file gets loaded on an Ajax callback? Easy--keep the module_load_include() function in hook_node_view, and use the form_load_include() function within your form definition. You still need to include the file within your module so that it is processed by Drupal on the initial page load, but once the file has been loaded with form_load_include(), it will be loaded anytime the form is called. From my_ajax_test.forms.inc:

/**
 * Form constructor for Ajax test form in node
 *
 */
function my_ajax_test_node_form($form, &$form_state) {
  form_load_include($form_state, 'inc', 'my_ajax_test', 'my_ajax_test.forms');
  $form['my_ajax_test_div'] = array(
    '#type' => 'container',
    '#tree' => TRUE,
    '#prefix' => '<div id="my-ajax-test-form-div">',
    '#suffix' => '</div>',
  );

  $form['my_ajax_test_div']['my_ajax_test_click_here'] = array(
    '#type' => 'button', 
    '#value' => 'Click this button',
    '#ajax' => array(
      'callback' => 'my_ajax_test_node_form_ajax',
      'wrapper' => 'my-ajax-test-form-div',
    ),    
    '#attributes' => array(
      'class' => array(
        'my-ajax-test-button',
      ),  
    ),       
  );
  
  $form['my_ajax_test_div']['my_ajax_test_no_function'] = array(
    '#type' => 'button', 
    '#value' => 'No function',
    '#ajax' => array(
      'callback' => 'my_ajax_test_node_form_ajax',
      'wrapper' => 'my-ajax-test-form-div',
    ),        
    '#attributes' => array(
      'class' => array(
        'my-ajax-test-button',
      ),  
      'disabled' => 'disabled',
    ),   
  );
 
  return $form;
}

As you can see with the form below, when you click the button "Click this button," the Ajax callback successfully changes the text of both buttons and renders the first button disabled while enabling the second button. But without the following line:

form_load_include($form_state, 'inc', 'my_ajax_test', 'my_ajax_test.forms');

the Ajax callback did nothing at all. See also the two buttons in the right sidebar: the same process is also true of blocks. Just use module_load_include() in hook_block_view() and form_load_include() in your form definition.

Tags