I've ran across and issue after building several forms with a table, pager and table sort that contains checkboxes / textfield elements and noticed quite a large problem. It seems the form isn't rebuilt when you sort the table, referencing the original form elements. I've tried to add ajax input elements and although the page rebuilt, the elements on the page will always trigger the originally rendered items.

I realize this might not have been a feature, or supported by query extenders, but I haven't found anyone that has come across this problem (or could find it). So I don't have to post all of my code, the tables/forms are similar to this example here.

Comments

tim.plunkett’s picture

Version: 7.14 » 8.x-dev
Priority: Major » Normal
Issue tags: +Needs backport to D7

Can you verify that this bug exists in Drupal 8?

r3z0nate’s picture

Version: 8.x-dev » 7.x-dev

I apologize, I thought I was posting as a 7.x issue.

I also thought this might have been an issue when using expressions in the query, and although I haven't done thorough testing, disabling them didn't seem to fix the problem.

tim.plunkett’s picture

Version: 7.x-dev » 8.x-dev

You did, but core has a backport policy which states that bugs have to be fixed in the newest version first, and then backported.

r3z0nate’s picture

Thanks, its the first time I've posted regarding core issues. Anyway, I'll try to confirm it over the weekend, but I would assume unless that section was completely revamped it would still be an issue/bug.

Maybe I'm incorrectly using fapi ajax in this situation, but this is the first time I've had issues and it seemed to start with the tablesort inclusion.

I also tried keying the form elements and row items, which might have put me on the right track, but more issues came up than were fixed.

tim.plunkett’s picture

Can you post your code somewhere? And exact steps to reproduce the bug?

r3z0nate’s picture

Sure, It's a couple thousand lines but I'll get a link up in a moment. Would the link I posted above work with the ajax callbacks or do you want the module?

As stated above, the one thing I could possible have been doing wrong was not keying the rows/form elements with the ID I wanted to update, but when trying that clicking on a header to sort would cause the first checkbox clicked to do nothing. Everything after that did worked, and it was better than changing the wrong rows but it still was an issue.

function bh_products_form($form, &$form_state) {
  
  $header = array(
    'sp_id' => array('data' => t('ID'), 'field' => 'sp_id'), 
    'title' => array('data' => t('Title'), 'field' => 'title'),
    'cost' => array('data' => t('Estimated Cost'), 'field' => 'est_cost'),
    'ordered' => array('data' => t('Order'), 'field' => 'ordered'),);

  $query = db_select('bh_inventory', 'a');
  $query->addField('a','title');
  $query->addField('a','est_cost');
  $query->addField('a','ordered');
  $query->addField('a','sp_id');
  $query->extend('PagerDefault')->limit(20)->extend('TableSort')->orderByHeader($header);
  $entries = $query->execute()->fetchAll();	
  
  $total = count($entries);
  $form['total']  = array('#markup' => "<h4>Total: $total</h4>",);
  
  $form['products'] = array(
    '#theme' => 'table',
    '#header' => $header,
    '#rows' => array(),
    '#tree' => TRUE,
    '#empty' => t('No Products'),
     '#attributes' => array('id' => 'edit-titles-results'),);
 
  foreach($entries as $record){

    $id = array('#value' => $record->sp_id,'#type' => 'hidden');

    $title = array(
      '#markup' => $record->title,
      '#prefix' => '<div class="edit-product-title"><label>Title</label>',
      '#suffix' => '</div>',);
	 
    $est_cost = array(
      '#type' => 'textfield',
      '#title' => t('Estimated Cost'),
      '#default_value' => $record->est_cost,
      '#size' => 40,
      '#prefix' => '<div class="edit-product-cost">',		
      '#suffix' => '</div>',
      '#maxlength' => 255,
      '#required' => FALSE,);

    $ordered = array(
      '#title' => t('Order'),	 
      '#id' => 'product-' . $record->sp_id . '-order',
      '#type' => 'checkbox',
      '#prefix' => '<div id="product-' . $record->sp_id . '-order-wrapper">',		
      '#suffix' => '</div>',
      '#return_value' => $record->sp_id,	  
      '#default_value' => $record->ordered,
      '#ajax' => array(
        'wrapper' => 'product-' . $record->sp_id . '-order-wrapper',
        'method' => 'replace',
        'callback' => '_bh_products_order',
      ),
    );	 
	 
    $form['products']['item'][] = array(
      'sp_id' => &$id,
      'title' => &$title,
      'cost' => &$est_cost,
      'ordered' => &$ordered);

    $form['products']['#rows'][] = array(
      array('data' => &$id, 'field' => 'sp_id'),
      array('data' => &$title, 'field' => 'title'),
      array('data' => &$est_cost, 'field' => 'cost'),
      array('data' => &$ordered, 'field' => 'ordered'),		  
    ); 
    unset($title, $est_cost, $id, $order);
  }
  
  $form['pager'] = array('#markup' => theme('pager'));
 
  return $form;
}

function _bh_products_order($form, $form_state) {
  $name = $form_state['triggering_element']['#name'];
  $name_1 = str_replace('products[item][', "", $name);
  $key = str_replace('][ordered]', "", $name_1);

  $sp_id = $form['products']['item'][$key]['sp_id']['#value'];
  $wrapper = '#product-'.$id.'-order-wrapper';

  $element = array('#markup' => '<div><label>Order</label></div>','#id' => 'product-' . $sp_id . '-order',);
  $output = drupal_render($element);
  $commands[] = ajax_command_replace($wrapper, $output);
  print ajax_render($commands);
  exit;
}
r3z0nate’s picture

Version: 8.x-dev » 7.x-dev

This is a simple version, and I hope a good example to get started. Basically the forms grew from simple forms with a checkbox being saved via a submit to forms with tablesort, expressions in the query so the headers could be sorted based on that data, and text fields added along with the checkbox. I noticed the problem then, but also added expressions included those fields in the table sorting around the same time. It is hard to pin it down to a fapi issue, tablesort issue, pager or database issue.

To me it seems like the form elements are always using the keys from when the form is originally built. I've confirmed this by noting which item is updated. I have no idea when to go from here. Like I said before, I added the ID to the $form['products']['item'] and table row which helped, but needed set the ID of the row to even make it possible to update the data. I have no idea why then after clicking sort the first item clicked won't update but any afterwards will.

r3z0nate’s picture

Unfortunately, I haven't found an answer to this problem and have come across another. It seems that occasionally the form tables completely stops working across the site. I'm unsure if advanced forms in tables are something that people just do not use, and the bugs are either unknown or happen to a select few, or I am completely missing something.

Either way, after working with Drupal for 4 years now, I haven't come across an issue so incredibly frustrating.

Status: Active » Closed (outdated)

Automatically closed because Drupal 7 security and bugfix support has ended as of 5 January 2025. If the issue verifiably applies to later versions, please reopen with details and update the version.