Drupal AJAX fires only once In Drupal 7, I have a form where I would like to do the following:


Display a list of options in a simple two column table
Selecting an action from a drop down list fires AJAX and replaces options in the table


I have code written and Drupal only posts values to the AJAX on the first time you pick a select. Does this just not work on form 'item' types? Note, there are also other forms on the page, but the form IDs are unique as are the form fields.

$form['new_date'] = array(
            '#type' =&gt; 'select',
            '#title' =&gt; 'Delivery Date',
            '#options' =&gt; $date,
            '#ajax' =&gt; array(
                'callback' =&gt; 'delivery_date_weekends',
                'wrapper' =&gt; 'dates-ajax',
                'method' =&gt; 'replace',
                'effect' =&gt; 'fade',
            ),
        );

$form['date_weekend'] = array(
                '#type' =&gt; 'item',
                '#prefix' =&gt; '&lt;div id="dates-ajax"&gt;',
                '#suffix' =&gt; '&lt;/div&gt;',
                '#markup' =&gt; '',
          );


Then in the AJAX callback, data is returned with #markup set to theme('table') of the results. It only works the first time around, I see the POST data in the Firebug console. Pick another drop down option, my table does not update.

Did I do something wrong here?

Edit: seems like the POST is making it, but the response is empty, but should not be.

Edit 2: Ajax Callback:

function delivery_date_weekends($form, $form_state) {

    $query = new EntityFieldQuery();
    $result = $query-&gt;entityCondition('entity_type', 'field_collection_item')
        -&gt;propertyCondition('item_id', $form_state['values']['rates'])
        -&gt;fieldCondition('field_delivery_basis', 'value', 'Weekly', '=');

    $startmonth = strtotime(date('m', $form_state['values']['new_date']).'/01/'.date('Y'));
    $endmonth = strtotime('+1 month', $startmonth);

    $query-&gt;fieldCondition('field_delivery_date_period', 'value', $startmonth, '&gt;=')
                -&gt;fieldCondition('field_delivery_date_period', 'value', $endmonth, '&lt;=');

    $result = $query-&gt;execute();

    if ($result) {
        $headers = array(
            array('data' =&gt; 'Weekend', 'class' =&gt; 'tableHeader-processed'),
            array('data' =&gt; '', 'class' =&gt; 'tableHeader-processed'),
        );

        $rates = entity_load('field_collection_item', array_keys($result['field_collection_item']));

        foreach ($rates as $key =&gt; $rate) {
            if ($rate-&gt;field_delivery_available['und'][0]['value']) {
                $rows[] = array('data' =&gt; array(date('M j, Y', $rate-&gt;field_delivery_date_period['und'][0]['value']), array('data' =&gt; 'delivery link', 'class' =&gt; array('fee'))));
            } else {
                $rows[] = array('data' =&gt; array(date('M j, Y', $rate-&gt;field_delivery_date_period['und'][0]['value']), array('data' =&gt; 'Not Available!')));
            }
        }

        $form['booking_weekend']['#markup'] = theme('table', array('header' =&gt; $headers, 'rows' =&gt; $rows, 'sticky' =&gt; FALSE));
    } else {
        $form['booking_weekend']['#markup'] = 'No delivery weekends exist for this month. Please select another date.';
    }

    return $form['booking_weekend'];
}


Basically when a month/year is selected, I am querying for dates (inside a field collection).
It's hard to say without actually running those queries but I think the problem is just because of a disparity in the names of your form elements.

In your form the element is defined as $form['date_weekend'] but in your callback you set an element called $form['booking_weekend']. 

This would probably be fine except that $form['booking_weekend'] doesn't have the #prefix and #suffix that $form['date_weekend'] does. Drupal replaces the entire wrapper element when it does an AJAX replace so if the new element doesn't have a wrapper with the same ID around it the next AJAX call won't work (as no element would exist with the correct ID).

I'd recommend changing the element names to match as this should solve the problem, but if you really need it to be a different element just add the wrapper around the new element in your callback:

// The rest of delivery_date_weekends() comes before this as normal...

  $form['booking_weekend']['#markup'] = theme('table', array('header' =&gt; $headers, 'rows' =&gt; $rows, 'sticky' =&gt; FALSE));
} else {
    $form['booking_weekend']['#markup'] = 'No delivery weekends exist for this month. Please select another date.';
}

$form['booking_weekend']['#prefix'] = '&lt;div id="dates-ajax"&gt;';
$form['booking_weekend']['#suffix'] = '&lt;/div&gt;';

return $form['booking_weekend'];