I have a form with a table (not a tableselect) that I use with 2 inputs: one to add some information and a button that (I hope) will delete its corresponding row when clicked. I also have a button in the form that should update the table's rows when clicked. Right now the data updates, but the inputs don't show up.

I'm guessing that the reason is that I am using an AJAX callback and ajax_command_replace on update, and theme_table to generate that part of the form. What do I need to do to get my theme_table function to also work on AJAX callback?

    // The theme function
    function sws_theme($existing, $type, $theme, $path) {
         return array(
             'sws_textfield_table' => array(
             'render element' => 'element'

    // theme_table
    function theme_sws_textfield_table($vars) {
        $element = $vars['element'];
        $rows = array();
        foreach (element_children($element) as $key) {
             $rows[] = array(
                  array('data' => $element[$key]['#id']),
                  array('data' => $element[$key]['#dates']),
                  array('data' => $element[$key]['#type']),
                  array('data' => $element[$key]['#qualified']),
                  array('data' => $element[$key]['#time']),
                  array('data' => $element[$key]['approval']), // Text input field for each row
                  array('data' => $element[$key]['remove']), // Click here to remove a table row and its data)

     $header = array(
            'id' => t('ID'),
            'dates' => t('Dates'),
            'type' => t('Type'),
            'qualified' => t('Qualified'),
            'time' => t('Time'),
            'approval' => t('Approved by'),
            'remove' => t('Remove')
         return theme('table', array('header' => $header, 'rows' => $rows, 'id' => 'sws_table'));

Here is the part of my hook_form_alter that pertains to this table:

$form['sws_import']['sws_table'] = array(
    '#theme' => 'sws_textfield_table',
    '#tree' => true,
    '#attributes' => array(
        'id' => 'sws_table'
    '#prefix' => '<div id="sws">',
    '#suffix' => '</div>'

// $overtime and $overtime_approved hold the unserialized values for the rows and the 'Approved' fields, respectively

for($ov = 1; $ov < count($overtime); $ov++) {
    $form['overtime_import']['overtime_table'][$ov]['#id'] = $overtime[$ov]['id'];
    $form['overtime_import']['overtime_table'][$ov]['#dates'] = $overtime[$ov]['dates'];
    $form['overtime_import']['overtime_table'][$ov]['#type'] = $overtime[$ov]['type'];
    $form['overtime_import']['overtime_table'][$ov]['#qualified'] = $overtime[$ov]['qualified'];
    $form['overtime_import']['overtime_table'][$ov]['#time'] = $overtime[$ov]['time'];

    $form['overtime_import']['overtime_table'][$ov]['overtime_approved_by'] = array(
        '#type' => 'textfield',
        '#title_display' => 'invisible',
        '#value' => $overtime_selected[$ov] ? $overtime_selected[$ov] : '',
        '#default_value' => $overtime_selected[$ov] ? $overtime_selected[$ov] : '',
        '#size' => 24,
        '#required' => TRUE,
        '#name' => 'approval[]',
        '#attributes' => array(
            'id' => 'approval'

    $form['overtime_import']['overtime_table'][$ov]['remove'] = array(
        '#type' => 'submit', 
        '#value' => t('Remove'),
        "#submit" => array('sws_empty_submit'),
        '#parents' => array('overtime_import', 'group_restid'),
        '#limit_validation_errors' => array(),
        '#ajax' => array(
                "callback" => 'sws_update_overtime_table',
                "wrapper" => 'sws_table',
                'progress' => array(
                    'type' => 'throbber'
                "event" => 'click',
                'prevent' => 'click'

I use the same theme_table function and form_alter code in the update AJAX callback, along with:

$commands = array();
$commands[] = ajax_command_replace("#swstable", theme('table', array(
    'header' => $header,
    'rows' => $overtime,
    'attributes' => array('class' => array('table'))
return array('#type' => 'ajax', '#commands' => $commands);

But like I said this code doesn't print the form fields in the table. How should I use AJAX callbacks on a table in a form?

  • UPDATE Have solved the issue with the inputs by simply adding a drupal_render($form['overtime_import']['overtime_table'][$ov]['overtime_approved_by']); after them. My only problem now is getting the Remove buttons to still be AJAX enabled when the table is regenerated, and not just submit the form. The Remove buttons work fine in deleting the chosen row when the form is first generated, but the class 'ajax-processsed' and the associated AJAX functionality are missing when the table is regenerated. – reramewo Nov 24 '15 at 8:54

Your Answer

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

Browse other questions tagged or ask your own question.