7

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' => 'select',
            '#title' => 'Delivery Date',
            '#options' => $date,
            '#ajax' => array(
                'callback' => 'delivery_date_weekends',
                'wrapper' => 'dates-ajax',
                'method' => 'replace',
                'effect' => 'fade',
            ),
        );

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

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->entityCondition('entity_type', 'field_collection_item')
        ->propertyCondition('item_id', $form_state['values']['rates'])
        ->fieldCondition('field_delivery_basis', 'value', 'Weekly', '=');

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

    $query->fieldCondition('field_delivery_date_period', 'value', $startmonth, '>=')
                ->fieldCondition('field_delivery_date_period', 'value', $endmonth, '<=');

    $result = $query->execute();

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

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

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

        $form['booking_weekend']['#markup'] = theme('table', array('header' => $headers, 'rows' => $rows, 'sticky' => 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).

2
  • Would you be able to update your question with the code for delivery_date_weekends() as well? – Clive Feb 10 '12 at 18:36
  • Added the callback – Kevin Feb 10 '12 at 18:49
5

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' => $headers, 'rows' => $rows, 'sticky' => FALSE));
} else {
    $form['booking_weekend']['#markup'] = 'No delivery weekends exist for this month. Please select another date.';
}

$form['booking_weekend']['#prefix'] = '<div id="dates-ajax">';
$form['booking_weekend']['#suffix'] = '</div>';

return $form['booking_weekend'];
5
  • Okay, I fixed all that and they are consistent. It still only works on the first time, then the second time the field does not update at all and there is no data in the response (and there should be). The query works fine. Even if it has no results, it should still return the 'No delivery weekends...' markup. – Kevin Feb 10 '12 at 19:13
  • Does it attempt to replace it the second time round, i.e. does it perform the fade animation and just replace it with the same table? And if not are you getting any js errors in the console? – Clive Feb 10 '12 at 19:19
  • No errors, no replace, doesn't seem like anything even happens. Data is still posted. Response is completely empty, almost as if Drupal knows it should do something, but not what. By 'empty' I mean I just see the generic commands returned, but all values are null, and it only has the 0 item (usually has 3). – Kevin Feb 10 '12 at 19:26
  • Kevin, did you ever get this to work? I am having the same issue where the ajax call will only fire once. And never again until the page is reloaded. – Brandon Bearden Jul 8 '12 at 23:03
  • Yes I did. Make sure you're returning the right elements in the AJAX callback so that it is still bound to the form element when it is re-rendered. I think that was my issue. – Kevin Jul 15 '12 at 17:09
0

I was struggling with similar issue, and finally found solution here:

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).

Very simple, but I've forgot about it. After correcting div-id problem disappeared :) Thanks, Clive!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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