I know, this [potentially serious] bug/issue might be being launched a bit late. Surprisingly, I couldn't find anything online which indicates that Drupal7's Ajax system seems to have a problem with ->extend('PagerDefault') and ->extend('TableSort') in the default configuration. When clicking either on the pager or the table head elements (made sortable), the system returns following error message:

Undefined index: form_build_id in ajax_get_form() (line 320 of /var/www/devdev/drupal7/includes/ajax.inc).

includes/ajax.inc (line 320):

  $form_build_id = $_POST['form_build_id'];

This means, quite obviously, that the POST variable 'form_build_id' cannot be found resp. is not available. I made several checks with my form: The 'form_build_id' becomes available e.g. straight after clicking a form element before the particular table (with the sortable header above and the pager below). Here comes the proof (;): form-h1Q-_7FcO8nFRRfueZSzHIMo7zLxs46_Uk5Wrhe6OS4 !
Straight after loading/rendering the pristine page/form [and without having clicked anything yet] via hook_menu()'s page callback the form_build_id does not exist. It doesn't matter whether the callback is drupal_get_form() or drupal_build_form(). Anyhow, in my eyes ->extend('PagerDefault') and ->extend('TableSort') should work by default and shouldn't need any additional workarounds/additions. Am I wrong?

Comments

Blooniverse’s picture

Issue summary: View changes

(ps) table deleted.

Blooniverse’s picture

Issue summary: View changes

(ps) layout stuff.

Blooniverse’s picture

... btw, I am aware of this old issue here: #295430: Default sort using tablesort_get_order() is broken. It seems to be still [or again?] haunting Drupal's tables! I, for instance, get a
Fatal error: [] operator not supported for strings in /var/www/devdev/drupal7/includes/tablesort.inc on line 172
when:
$arr_thead[] = array('data' => t('ZIP code'), 'field' =>'zPLZb', 'sort'=>'asc');
... *sigh*

Blooniverse’s picture

Posting a hint about #97293: Tablesort cleanup - related to my comment#1!

tim.plunkett’s picture

Priority: Major » Normal
Status: Active » Postponed (maintainer needs more info)

Can you post exact steps to reproduce?

If you wrote any custom code, can you provide that as well?

Blooniverse’s picture

Hello Tim!

Thanx a lot for you quick response. I am very super-glad about your community service, I can tell you!

Well, it is actually quickly explained. After clicking on one of the table header titles, I get:
Notice: Undefined index: form_build_id in ajax_get_form() (Zeile 320 von /var/www/devdev/drupal7/includes/ajax.inc).

When I look at the table header titles, the message in the browser status is for instance drupal7.dev/ajax?sort=asc&order=foo-title -- which looks wrong to me straight way, since it should be order=foo, shouldn't it?

Devel's Krumo backtrace points this out was well:


main() (Array, 2 elements)
   file (String, 12 characters ) index.php:21
   args (Array, 3 elements)
     sort (String, 3 characters ) asc
     order (String, 12 characters ) foo-title
     q (String, 11 characters ) system/ajax

Below you find my module code.

function _load_table($arg) {
  $int_plz        = intval($arg);
  $arr_thead      = array();
  $arr_rows       = array();
  $str_themed     = '';
  
  $arr_thead[] = array('data' => '[x]');
  $arr_thead[] = array('data' => t('foo-title'), 'field' => 'foo');                                       
  $arr_thead[] = array('data' => t('bar-title'), 'field' => 'bar');                            
  
  $query = db_select('table', 't')
            ->extend('PagerDefault')
            ->extend('TableSort')
            ->orderByHeader($arr_thead)
            ->condition('t.foo', $arg, '=')
            ->fields('t', array('foo', 'bar'))
            ->limit(3)   
            ->orderBy('bar', 'DESC');  
  $qry_result = $query->execute();
              
  $cnt = 0;
  foreach ($qry_result as $record) {
    $cnt++;
    $_SESSION['formx']['table']['chkbx'][$cnt]['foo'] = $record->foo;
    $arr_rows[] = 
      array(  
        'data' => array(
          array('data' => '[x]', 'class' => array('css-class-cell-000', 'css-input')),
          array('data' => $record->foo, 'class' => array('css-class-cell-001', 'nbr')), 
          array('data' => $record->bar, 'class' => array('css-class-cell-002', 'txt')),
        ), 
        'class' => array('css-class-row-'.$cnt, 'baz-class'),
    );
  }
  
  $arr_tblattribs = array(
    'class' => array('css-class-table01', 'css-class-table01-xyz'),
    'id'    => array('id-table'),
    'name' =>  array('name-table'),
  );    
  $str_themed .= theme('table', array('header' => $arr_thead, 'rows' => $arr_rows, 'attributes' => $arr_tblattribs, 'sticky' => TRUE));
  $str_themed .= theme('pager', array('tags' => array()) );
  
  return $str_themed;
}

Again, thanks a lot for looking into this [nasty] thing.

Blooniverse’s picture

Issue summary: View changes

(ps) last layout changes.

acrussell’s picture

Priority: Normal » Critical
Status: Postponed (maintainer needs more info) » Needs work

I am also getting this problem.
I am very surprised that it is unresolved! Either very few people are usuing ajax with tableselect (seems unlikely?)
or there is some workaround that I just haven't run across yet.
Below is an example which uses ajax and tableselect to reproduce the white screen of death problem I get.
The example is contrived and somewhat patched together but it reproduces the problem exactly it seems.
If you have the form recreated by typing something in the textfield and hitting enter and then click "next" you will get the white screen of death. If you click back Drupal informs you of the error
Notice: Undefined index: form_build_id in ajax_get_form() (line 320 of /var/www/html/includes/ajax.inc).
I notice that clicking "next" the URL changes to something which is clearly not right:
?q=system/ajax&page=1

Below is the module code. If there is some workaround to getting ajax and tableselect to work well together I would appreciate knowing what it is! This seems to me to be a fairly serious bug!


function temp_module_menu() {
    $items['temp_module'] = array(
        'title' => 'Drupal 7 test pager',
        'type' => MENU_CALLBACK,
        'page callback' => 'temp_module_test_pager',
        'access callback' => TRUE,
    );
    return $items;
}

function temp_module_test_pager() {
    return drupal_get_form('temp_form');
}

function list_refresh($form, &$form_state) {
    return $form;
}

function temp_form($form, &$form_state) {
    $form['#prefix'] = '<div id="search_list">';
    $form['#suffix'] = '</div>';

    $form['title'] = array(
        '#type' => 'textfield',
        '#title' => t('Course Title'),
        '#size' => 30,
        '#maxlength' => 30,
        '#required' => FALSE,
        '#prefix' => '<td>',
        '#suffix' => '</td></tr>',
        '#ajax' => array(
            'callback' => 'list_refresh',
            'wrapper' => 'search_list',
            'keypress' => TRUE,
            'method' => 'replace',
            'effect' => 'fade'
        ),
    );
//Create a list of headers for your Html table (see Drupal 7 docs for theme_table here
    $header = array(
        'nid' => t('title'),
        'title' => t('nid'),
        'type' => t('type'),
        'created' => t('created'),
        'status' => t('status'),
    );

//Create the Sql query. This uses various parts of Drupal 7's new DBTNG database abstraction layer.

    $query = db_select('node', 'n')
            ->condition('status', 1) //Only published nodes, change condition as it suits you
            ->extend('PagerDefault')  //Pager Extender
            ->limit(2)    //2 results per page
            ->extend('TableSort')  //Sorting Extender
            ->orderByHeader($header)//Field to sort on is picked from $header
            ->fields('n', array(
        'nid',
        'title',
        'type',
        'created',
        'status',
            ));

    $results = $query
            ->execute();

    $rows = array();
    foreach ($results as $node) {
        $rows[$node->nid] = array(
            'title' => l($node->title, 'node/' . $node->nid),
            'nid' => $node->nid,
            'type' => $node->type,
            'created' => format_date($node->created),
            'status' => $node->status
        );
    }
    $form['registration_table'] = array(
        '#type' => 'tableselect',
        '#header' => $header,
        '#options' => $rows,
        '#js_select' => FALSE,
        '#multiple' => TRUE,
        '#prefix' => '<table><tr><td>',
        '#suffix' => '</td></tr>',
    );
    $form['submit'] = array('#type' => 'submit',
        '#value' => t('Register'),
        '#disabled' => FALSE,
        '#prefix' => '<tr><td>',
        '#suffix' => '</td></tr></table>');
    $form['pager'] = array('#markup' => theme('pager'));
    return $form;
}

tim.plunkett’s picture

Version: 7.16 » 8.x-dev
Priority: Critical » Normal
Status: Needs work » Active
Issue tags: +Needs backport to D7

Fixing tags

acrussell’s picture

Is there any alternative or workaround (or even a tentative D7 patch?) that can be used while waiting for the backport?
I would like this functionality for a current project and this is an unforeseen bottleneck!

Blooniverse’s picture

@acrussell: Have you tried the patch on http://drupal.org/node/97293#comment-5813270 (referred to in comment#2) already? If you do so, please let us know immediately about the outcome!!!

Blooniverse’s picture

... yes, please let us know, @esprit2!

mazdakaps’s picture

So what was the solution?

eMuse_be’s picture

I added these extra fields in my template (they seemed logical). Everything works for me:

print drupal_render($form['form_build_id']);
print drupal_render($form['form_token']);
print drupal_render($form['form_id']);
print drupal_render($form['webform_ajax_wrapper_id']);

eMuse_be’s picture

Issue summary: View changes

(ps)

joshtaylor’s picture

Ran into this today because I forgot:

<?php print drupal_render_children($form); ?>

Woops :).

pavlos.katsonis’s picture

I'm using Drupal 7 and have the same problem, but I don't understand where to put the 4 drupal_render commands. I don't have any templete file, just include files. The relevant code follows:

class xxxEntityUIController extends EntityDefaultUIController {
...
  public function hook_menu() {
    $items = parent::hook_menu();
    .....
    $items['player/%entity_object/gamelog'] = array(
      'load arguments' => array(0, 1),
      'title' => t('Game Log'),
      'access arguments' => array('view basket entities'),
      'page callback' => 'drupal_get_form',
      'page arguments' => array('player_gamelog_form', 0, 1),
      'type' => MENU_LOCAL_TASK,
      'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
      'weight' => -40,
    );
    .....
    return $items;
  }

  public function hook_forms() {
    $forms = parent::hook_forms();
    $forms['player_gamelog_form'] = array('callback' => 'player_gamelog_form');
    ....
    return $forms;
  }
}
function player_gamelog_form($form, &$form_state, $entity_type = 'player', $entity = NULL) {
  drupal_set_title (is_null($entity) ? 'Unknown' : $entity->defaultLabel());
  $values = key_exists('values', $form_state) ? $form_state['values'] : array();
  $form['filters'] = array(
    '#type' => 'container',
    '#attributes' => array('class' => array('container-inline')),
  );
  $form['filters']['season'] = array(
    '#type' => 'select',
    '#title' => t('Season'),
    '#options' => ..... ,
    '#ajax' => array(
      'callback' => 'basketentities_param_form_callback',
      '#path' => array('log_table'),
      'wrapper' => 'log_table',
      'method' => 'replace',
      'effect' => 'fade',
    ),
  );

  $header = array(
    'Game',
    array ('data' => 'Season', 'field' => 'season', 'sort' => 'DESC'),
    array ('data' => 'Day', 'field' => 'day', 'sort' => 'DESC'),
   ......
    array ('data' => 'PF', 'field' => 'pf'),
  );
  $sq = db_select('bs_stats_players', 'p')
    ->fields('p', array('game', 'season', 'day', ..... 'pf'))
    ->extend('TableSort')->orderByHeader($header)
    ->extend('PagerDefault')->limit(5);
  ....
  if(key_exists('season', $values) && (int)$values['season'] !== 0)
    $sq->condition('season', (int)$values['season']);

  $form['log_table'] = array(
    '#theme' => 'table',
    '#header' => $header,
    '#rows' => array(),
    '#empty' => t('No games.'),
    '#prefix' => '<div id="log_table">',
    '#suffix' => '</div>',
  );
  foreach($sq->execute() as $row) {
    $game = ....
    $link = ....
    $form['log_table']['#rows'][] = array(
       ....
    );
  }
  $form['log_pager'] = array('#theme' => 'pager');


  return $form;
}

I would be grateful if you could point me to the right direction, since I'm quite new to Drupal development.

darth_revan43@yahoo.com’s picture

I've posted a workaround for this issue here for anyone who is struggling with this.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

weeger’s picture

Work fine with #12.

Why not create a method for system required form field like drupal_render_form_header($ajax = FALSE); ?

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

pameeela’s picture

Status: Active » Closed (cannot reproduce)
Issue tags: +Bug Smash Initiative

There were never really any steps to reproduce here and it only seemed to be affecting custom code, so I'm going to close this.

If anyone still has the issue in D7 or D8 please open a new ticket with clear steps to reproduce, starting with 'Install Drupal'. If your issue only occurs with custom code, then it's probably a support request rather than a bug.