As implied in this question, I'm adding a list of similar child forms to my parent form with the following code:

foreach ($form_state['items'] as $key => $item) {

    $existing = NULL;
    if (isset($form['item_holder'][$key])) {
        $existing = $form['item_holder'][$key];

    $state = NULL;
    if (isset($form_state['item_holder'][$key])) {
        $state = $form_state['item_holder'][$key];

    $el = item_form_edit($existing, $state, $item);

    $form['item_holder'][$key] = $el;   

I am calling the form function directly because drupal_get_form() was causing errors due to confusion about which form was being submitted.

My child form type has ajax callbacks that return parts of it $form object. But the child's callback function is receiving the parent form's object and causing an error trying to return parts of the child form.

How do I sort out ajax calls between parent and child $form contexts? Do I need to go back and add the child forms with drupal_get_form()? If so, how do I avoid confusing which form has been submitted?

  • 1
    Note that there is no such thing as a nested form. That is simply impossible, a <form> tag may no contain another <form> tag, that has nothing to do with using drupal_get_form().
    – Berdir
    Commented Mar 14, 2012 at 22:18
  • Interesting - I agree that <form> should not contain <form> but my approach below is working great on chrome, firefox, safari and IE. Commented Mar 15, 2012 at 0:43
  • For a variety of reasons, I abandoned the manual subform approach and am working with the Subform module. Next steps here >> drupal.stackexchange.com/questions/25725/…. Commented Mar 17, 2012 at 14:12

1 Answer 1


It turns out Drupal will distinguish ajax for subforms automatically if you work within the system - which I was not.

Instead of calling the form builder function directly (bad), I use drupal_get_form() so the code above becomes:

foreach ($form_state['items'] as $key => $item) {

    $form['item_holder'][$key] = drupal_get_form('item_form_edit', $item);


I was previously loading the subitem's code with module_load_include(). I now load the sub-item's code with form_load_include() which should make a cached version of this form load correctly.

Since I am building a list of similar subforms, the subform needs to make sure it gets a unique wrapper:

function item_form_edit($form, &$form_state, $edit = NULL) {

    $id_string = 'sub-item-form';
    $unique_id = drupal_html_id($id_string);    

    $form['#prefix'] = '<div id="' . $unique_id . '">';
    $form['#suffix'] = '</div>';


    return $form;

Now, an AJAX element on the subform can replace that subform with

    '#ajax' => array(
        'wrapper' => $unique_id,
        'callback' => 'subform_callback',

In this example, the entire subform is being replaced by the callback:

function subform_callback($form, &$form_state) {
    return $form;

My subform builder function is in a separate file, so hook_init() needs to make Drupal aware of the subform code during AJAX requests:

if ($_GET['q'] == 'system/ajax' || strstr($_GET['q'], 'file/ajax/')) {
    if (preg_match('/item_form_edit/', $_POST['form_id'])) {
        module_load_include('inc', 'mymodule', 'file_with_item_form');

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.