I'm trying to theme a node form with <?php theme('table', $headers, $rows); ?>

the relevant part of hook_form

<?php	
foreach ($nodes as $error){	// for each error found in the layout table we create 2 fields;
	// Define a fieldset which will contain the form fields for each row/error of the sheet
	$iter_error++; // increment the iteration by 1
		$form['sheet_wrapper'][$error->nid] = array(
			//'#type' => 'fieldset',
			'#tree' => TRUE,
			'#description' => t($error->title), 
			'#weight' => $iter_error,
			'#theme' => 'sheet_table_edit', // use this theme function to theme this part of the form
			//'#prefix' => '<div class="clear-block" id="sheet-error">',
			//'#suffix' => '</div>',
		);  
		// create the link
		$form['sheet_wrapper'][$error->nid]['name'] = array(
			'#prefix' => '<a href="../' .$error->nid .'">',
			'#value' => t($error->title),
			'#suffix' => '</a>',
					);
		$form['sheet_wrapper'][$error->nid]['amount'] = array(
			'#type' => 'textfield',
			'#title' => t('amount'),
			'#size' => 3,
			'#maxlength' => 3,
			'#description' => t('amount of errors'),
			'#default_value' => isset($node->sheet_wrapper[$error->nid]['amount'] ) ? $node->sheet_wrapper[$error->nid]['amount'] : '', // default value		
			'#attributes' => array('tabindex' => $iter_error),
			);
		$form['sheet_wrapper'][$error->nid]['remarks'] = array(
			'#type' => 'textfield',
			'#title' => t('remarks'),
			'#size' => 50,
			'#maxlength' => 127,
			'#description' => t('remarks concerning the error'),
			'#default_value' => isset($node->sheet_wrapper[$error->nid]['remarks']) ? $node->sheet_wrapper[$error->nid]['remarks'] : '',
			'#attributes' => array('tabindex' => $size_error + $iter_error),	
		);		
	}
}    
  return $form;
  }
?>

and the theme function that uses theme('table',...

<?php
function theme_sheet_table_edit($form) {
  $rows = array();
  $headers = array(
    t('Error'),
    t('Amount'),
    t('Remarks'),  // Blank header title for the remove link.
  );

foreach ($form['sheet_wrapper'] as $nid=>$error) {   <<---- error here
    // No need to print the field title every time.
    unset(
      $error['name']['#title'],
      $error['amount']['#title'],
      $error['remarks']['#title']
    );

    // Build the table row.
    $row = array(
      'data' => array(
        array('data' => drupal_render($error['name'])),
        array('data' => drupal_render($error['amount'])),
        array('data' => drupal_render($error['remarks'])),
      ),
    );

    $rows[] = $row;
  }

  $output = theme('table', $headers, $rows);
  $output .= drupal_render($form);
  return $output;
}
?>

i get this error:
warning: Invalid argument supplied for foreach() in D:\xampp\htdocs\drupal\sites\default\modules\sheet\sheet.module on line 341.

Comments

yangke’s picture

my output (what you see) is an empty table (only headers) for every error that is defined by sheet_wrapper. which is not good because i should have 1 table and 1 row for every error.

nevets’s picture

This line foreach ($nodes as $error){ lacks context. Where does $nodes come from, I would guess it's an empty array.

yangke’s picture

my form displays a table of errors. The user can input the amount for each. The errors come from a database table (number of errors and order can be changed). $nodes is an array containing the different errors (they are the nid of different error nodes (a cck content type) )

<?php

//title and bodyfields get setup here

  // create a wrapper around the errorsheet part
  // the form tree looks like this:	sheet_wrapper	->   errornid (one for every error)	->   amount
  //																					->   remarks
  //												->   othererrornid					->   amount
  //																					->   remarks
  //												->   and another errornid			->   ...
  $form['sheet_wrapper'] = array(
    '#tree' => TRUE,
    '#weight' => 5,
    //'#prefix' => '<div class="clear-block" id="sheet-wrapper">',
    //'#suffix' => '</div>',
	'#prefix' => '<table>',
    '#suffix' => '</table>',
	'#theme' => 'sheet_table_edit', // use this theme function to theme this part of the form
  );
// code to create formfields based on a layout array (which is a content type)
$layout=36;  // this value should be assigned on settings page: variable_get('sheet_layout', array('36'))
// a query to get all the errors listed in the chosen layout
$query=db_query("SELECT * FROM {content_field_sheetlayout_error} WHERE {nid}=%d",$layout);
if ($query != FALSE) {													// only continue if the query was successful
	while($row = db_fetch_array($query)) {								// assign the rows to a variable called row
		$nodes[] = node_load($row['field_sheetlayout_error_nid']); 		// load the error nodes and put them in an array
	}
	$size_error=sizeof($nodes);
	$iter_error=0; // define an iteration variable
?>

note: i moved '#theme' => 'sheet_table_edit', to $form['sheet_wrapper']

still have an error with foreach, maybe some variablename that isn't known anymore in the theme function??

yangke’s picture

my theme function (working):

<?php
function theme_sheet_table_edit($form) {
  $rows = array();
  $headers = array(
	t('Category'),
    t('Error'),
    t('Amount'),
    t('Remarks'),
  );

foreach (element_children($form) as $error) {
    // No need to print the field title every time.
   unset(
      $form[$error]['name']['#title'],
      $form[$error]['amount']['#title'],
      $form[$error]['remarks']['#title']
    );

    // Build the table row.
    $row = array(
      'data' => array(
		array('data' => 'abc '.$error),
        array('data' => drupal_render($form[$error]['name'])),
        array('data' => drupal_render($form[$error]['amount'])),
        array('data' => drupal_render($form[$error]['remarks'])),
      ),
    );

    $rows[] = $row;
  }

  $output = theme('table', $headers, $rows);
  $output .= drupal_render($form);
  return $output;
}
?>

my tree structure is however:
sheet_wrapper -> 'some_error_nid'(from a table) -> name
-> amount
-> remarks
QUESTION:
TREE is TRUE,
so why do i have to leave the sheet_wrapper.
Why is it $form[$error]['name'] and not $form['sheet_wrapper'][$error]['name'] ??

thanks