Forms API Question - Node with table like poll.module
Hello All, I'm developing some modules to manage my computer business, and to do invoice, purchase orders, timesheets etc. I was using a table in the form in 4.6.3, but things are different in 4.7. The code below looks the closert so far, is there a better way to do this anybody can recommend? I've looked at the modules that use arrays/rows, like poll and system, but they aren't really doing what i'm trying to. Or do I just need to use css in the theme it to get the correct display? I'm open to suggestions. TIA Simon 4.6.3 ------- $header = array(t('Time'), t('Customer'), t('Comments')); $rows = array(); $count = count($node->timesheet_time); if ($count < 5) { $count = 5; } if ($_POST['edit']['timesheet_links_more'] == 1) { $count += 5; } for ($i = 0; $i < $count; $i++) { $row = array(); $row[] = form_textfield('', 'timesheet_time][' . $i, $node->timesheet_time[$i], 6, 6); $row[] = form_autocomplete('', 'timesheet_customer][' . $i, $node->timesheet_customer[$i], 30, 128, 'contacts/autocomplete_customer', $type); $row[] = form_textfield('', 'timesheet_comments][' . $i, $node->timesheet_comments[$i], 30, 255); //$row[] = form_textarea('', 'timesheet_comments][' . $i, $node->timesheet_comments[$i], 20, 2); $rows[$i] = $row; } $output .= form_item(t('Timesheet Entries'), theme('table', $header, $rows)); 4.7 ------ // If the user pressed the button asking for more rows, add more if ($_POST['edit']['timesheet_links_more'] == 1) { $count += 5; } $form['entries'] = array( '#type' => 'fieldset', '#title' => t('Timesheet Entries'), '#tree' => TRUE, ); // Now actually display the rows for ($i = 0; $i < $count; $i++) { $form['entries'][$i] = array( '#type' => 'fieldset', '#tree' => TRUE, ); $form['entries'][$i]['timesheet_time'] = array( '#type' => 'textfield', '#size' => 6, '#maxlength' => 6, '#default_value' => $node->timesheet_time[$i], '#prefix' => '<table><tr><td>', '#suffix' => '</td>', ); $form['entries'][$i]['timesheet_customer'] = array( '#type' => 'textfield', '#size' => 30, '#maxlength' => 128, '#autocomplete_path' => 'customer/autocomplete', '#default_value' => $node->timesheet_customer[$i], '#prefix' => '<td>', '#suffix' => '</td>', ); $form['entries'][$i]['timesheet_comments'] = array( '#type' => 'textfield', '#size' => 30, '#maxlength' => 255, '#default_value' => $node->timesheet_comments[$i], '#prefix' => '<td>', '#suffix' => '</td></tr></table>', ); }
I'm doing a little of the same kind of updates to some modules and I've found that the system.module settings forms are an excellent example of how to do form tables. The basic idea is to build the form, then put all the table rendering into a theme function. As you build the table you call form_render() on the contents of each cell. Finally, you call: $output .= theme('table',...) $output .= form_render($form); return $output; The cool part is that anything you haven't rendered in the table (like submission buttons) gets rendered below it. If that doesn't make sense or something's incorrect let me know, as I said I've just kind of figured it out. andrew On 11/11/05, Simon Lindsay <simon@dirtbike.ws> wrote:
Hello All,
I'm developing some modules to manage my computer business, and to do invoice, purchase orders, timesheets etc. I was using a table in the form in 4.6.3, but things are different in 4.7.
The code below looks the closert so far, is there a better way to do this anybody can recommend? I've looked at the modules that use arrays/rows, like poll and system, but they aren't really doing what i'm trying to.
Or do I just need to use css in the theme it to get the correct display?
I'm open to suggestions.
TIA
Simon
4.6.3 ------- $header = array(t('Time'), t('Customer'), t('Comments')); $rows = array(); $count = count($node->timesheet_time); if ($count < 5) { $count = 5; } if ($_POST['edit']['timesheet_links_more'] == 1) { $count += 5; } for ($i = 0; $i < $count; $i++) { $row = array(); $row[] = form_textfield('', 'timesheet_time][' . $i, $node->timesheet_time[$i], 6, 6); $row[] = form_autocomplete('', 'timesheet_customer][' . $i, $node->timesheet_customer[$i], 30, 128, 'contacts/autocomplete_customer', $type); $row[] = form_textfield('', 'timesheet_comments][' . $i, $node->timesheet_comments[$i], 30, 255); //$row[] = form_textarea('', 'timesheet_comments][' . $i, $node->timesheet_comments[$i], 20, 2);
$rows[$i] = $row; }
$output .= form_item(t('Timesheet Entries'), theme('table', $header, $rows));
4.7 ------
// If the user pressed the button asking for more rows, add more if ($_POST['edit']['timesheet_links_more'] == 1) { $count += 5; }
$form['entries'] = array( '#type' => 'fieldset', '#title' => t('Timesheet Entries'), '#tree' => TRUE, );
// Now actually display the rows for ($i = 0; $i < $count; $i++) { $form['entries'][$i] = array( '#type' => 'fieldset', '#tree' => TRUE, ); $form['entries'][$i]['timesheet_time'] = array( '#type' => 'textfield', '#size' => 6, '#maxlength' => 6, '#default_value' => $node->timesheet_time[$i], '#prefix' => '<table><tr><td>', '#suffix' => '</td>', );
$form['entries'][$i]['timesheet_customer'] = array( '#type' => 'textfield', '#size' => 30, '#maxlength' => 128, '#autocomplete_path' => 'customer/autocomplete', '#default_value' => $node->timesheet_customer[$i], '#prefix' => '<td>', '#suffix' => '</td>', );
$form['entries'][$i]['timesheet_comments'] = array( '#type' => 'textfield', '#size' => 30, '#maxlength' => 255, '#default_value' => $node->timesheet_comments[$i], '#prefix' => '<td>', '#suffix' => '</td></tr></table>', );
}
// Now actually display the rows for ($i = 0; $i < $count; $i++) { $form['entries'][$i] =
Please look at the flowcharts http://drupal.org/node/37194 At this step you display nothing, you are building the form. Later on, you'll have a chance to theme your form (that it's only a part of a bigger form, that does not matter). so $form['entries']['#theme'] = 'theme_function_here'; If you need more advice (there are a lot of custom theme'd forms now in core) do not hesitate to write devel again. Regards NK
$form['entries']['#theme'] = 'theme_function_here';
Further clarification: form['entries']['#theme'] = 'mymodule_foo'; function theme_mymodule_foo($form) { } For examples, I'd grep on element_children (though there are quite a few forms that got updated before element_children was born). Regards NK
Karoly Negyesi wrote:
form['entries']['#theme'] = 'mymodule_foo';
function theme_mymodule_foo($form) { }
For examples, I'd grep on element_children (though there are quite a few forms that got updated before element_children was born).
OK, but the timesheet module is an extension of node.module, and you're supposed to "return $form;" at the end of the "function timesheet_form(&$node)", not "return drupal_get_form('timesheet_entries', $form);". However, doing the "return $form" means that the theme doesn't get called, and doing the "drupal_get_form" gives array errors. I can't find a module that extends node that uses the themeing for node submission (despite quite a bit of grepping), although several use it for administration. If anyone can point one out to me, or where I'm going wrong, that would be great. Simon
On Sat, 12 Nov 2005 12:42:46 +0100, Simon Lindsay <simon@dirtbike.ws> wrote:
Karoly Negyesi wrote:
form['entries']['#theme'] = 'mymodule_foo'; function theme_mymodule_foo($form) { } For examples, I'd grep on element_children (though there are quite a few forms that got updated before element_children was born).
OK, but the timesheet module is an extension of node.module, and you're supposed to "return $form;" at the end of the "function timesheet_form(&$node)", not "return drupal_get_form('timesheet_entries', $form);".
Yes. Return $form and it'll call theme_mymodule_foo with the array in $form['entries'] Regards NK
simon, please visit the core examples section of the handbook: http://drupal.org/node/36052 i believe you'll find that the system_user example and the system_themes example have what you're looking for. also, if you haven't yet, please visit the general forms API documentation at: http://drupal.org/node/33338 at this point, i believe the doc team has covered most of the issues necessary to convert a module to the API. chad
-----Original Message----- From: Simon Lindsay [mailto:simon@dirtbike.ws] Sent: Saturday, November 12, 2005 04:43 To: development@drupal.org Subject: Re: [development] Forms API Question - Node with tablelike poll.module
Karoly Negyesi wrote:
form['entries']['#theme'] = 'mymodule_foo';
function theme_mymodule_foo($form) { }
For examples, I'd grep on element_children (though there are quite a few forms that got updated before element_children was born).
OK, but the timesheet module is an extension of node.module, and you're supposed to "return $form;" at the end of the "function timesheet_form(&$node)", not "return drupal_get_form('timesheet_entries', $form);".
However, doing the "return $form" means that the theme doesn't get called, and doing the "drupal_get_form" gives array errors.
I can't find a module that extends node that uses the themeing for node submission (despite quite a bit of grepping), although several use it for administration. If anyone can point one out to me, or where I'm going wrong, that would be great.
Simon
participants (4)
-
andrew morton -
Apartment Lines -
Karoly Negyesi -
Simon Lindsay