Making a custom form element AJAX aware How should I go about making my custom Drupal 7 Form element support AJAX events, just like other standard FAPI elements?

For example, with a drop-down list, I would do this:

$element['book'] = array(
  '#type' =&gt; 'select',
  '#title' =&gt; t('Book'),
  '#options' =&gt; $books,
  '#default_value' =&gt; $default_book,
  '#ajax' =&gt; array(
    'wrapper' =&gt; 'replace-me',
    'callback' =&gt; 'replacement-callback',
    'method' =&gt; 'replace',
  ),
);


But now that '#type' is my own custom element, the '#ajax' property is ignored. This is what I have implemented thus far:

function mymodule_element_info() {
  return array(
    'customelement' =&gt; array(
      '#input'          =&gt; TRUE,
      '#process'        =&gt; array('customelement_process'),
      '#theme'          =&gt; array('customelement'),
      '#theme_wrappers' =&gt; array('form_element'),
      '#tree'           =&gt; TRUE,
    ),
  );
}

function mymodule_theme($existing, $type, $theme, $path) {
  return array(
    'customelement' =&gt; array(
      'render element' =&gt; 'element',
    ),
  );
}

function theme_customelement($variables) {
  // render some elements
  return $output;
}

function form_type_customelement_value($element, $input = FALSE, &amp;$form_state) {
  // manipulate form values
  return $input
}

function customelement_process($element, &amp;$form_state, $complete_form) {

  // build the compound form array
  $element['#tree'] = TRUE;

  $element['book'] = array(
    '#type' =&gt; 'select',
    '#title' =&gt; t('Book'),
    '#options' =&gt; $books,
    '#required' =&gt; true,
  );

  $element['chapter'] = array(
    '#type' =&gt; 'textfield',
    '#title' =&gt; t('Chapter'),
    '#size' =&gt; 3,
    '#maxlength' =&gt; 3,
    '#required' =&gt; true,
  );

  return $element;

}


Using my custom element in a form goes like this:

function mymodule_menu() {
  $items = array();

  $items['path/to/page'] = array(
    'title'            =&gt; 'Test form',
    'type'             =&gt; MENU_LOCAL_TASK,
    'weight'           =&gt; 30,
    'page callback'    =&gt; 'drupal_get_form',
    'page arguments'   =&gt; array('mymodule_callback_testform'),
    'access callback'  =&gt; 'user_access',
    'access arguments' =&gt; array('mymodule_admin'),
  );

  return $items;
}

function mymodule_callback_testform() {
  $form = array();

  $form['test_element'] = array(
    '#type' =&gt; 'customelement',
    '#title' =&gt; 'Custom element test',
    '#required' =&gt; TRUE,
    '#ajax' =&gt; array(
      ... // this has no effect :(
    ),
  );

  return $form;
}


But unfortunately it doesn't "magically" support AJAX. I would like to trigger a Drupal AJAX event when any sub-element of my custom element has triggered certain events.
It has no effect because Drupal doesn't know what event to fire on.

If you look at the switch statement in ajax_pre_render_element() you can see that it has default events for all core element types. But it it doesn't know about your element type, and no event is provided, so it doesn't know how to continue. It returns the element as-is rather than attempt to make a decision its not qualified to make.

To fix you should just be able to pick an appropriate event for the code to fire on, e.g.

$form['test_element'] = array(
  '#type' =&gt; 'customelement',
  '#title' =&gt; 'Custom element test',
  '#required' =&gt; TRUE,
  '#ajax' =&gt; array(
    'event' =&gt; 'click',
    ...
  ),
);