%myvars; ]> Using Form Builder: building html forms dynamically Overview ($Id: form-builder.xml,v 1.10 2017/08/07 23:47:54 gustafn Exp $) OpenACS has a form manager called ad_form. Ad_form has an adaptable UI. Error handling includes inline error reporting, and is customizable. However, ad_form can be tricky to use. In addition to this document, the ad_form api documentation is helpful. Multi-part Elements Some elements have more than one choice, or can submit more than one value. SELECT elements Creating the form element Populate a list of lists with values for the option list. set foo_options [db_list_of_lists foo_option_list " select foo, foo_id from foos "] The variable foo_options should resemble {{first foo} 1234} {{second foo} 1235} Within ad_form, set up the element to use this list: {foo:text(select) {label "Which Foo"} {options $foo_options} } This will result in a single name/value pair coming back in the submitted form. Handle this within the same ad_form structure, in the -new_data and -edit_data. In the example, it is available as $foo See also the W3C spec for "The SELECT, OPTGROUP, and OPTION elements". Using refreshes to pull additional information from the database A situation you may run into often is where you want to pull in form items from a sub-category when the first category is selected. Ad_form makes this fairly easy to do. In the definition of your form element, include an html section {pm_task_id:integer(select),optional {label "Subject"} {options {$task_options}} {html {onChange "document.form_name.__refreshing_p.value='1';submit()"}} {value $pm_task_id} } What this will do is set the value for pm_task_id and all the other form elements, and resubmit the form. If you then include a block that extends the form, you'll have the opportunity to add in subcategories: if {[info exists pm_task_id] && $pm_task_id ne ""} { db_1row get_task_values { } ad_form -extend -name form_name -form { ... } Note that you will get strange results when you try to set the values for the form. You'll need to set them explicitly in an -on_refresh section of your ad_form. In that section, you'll get the values from the database, and set the values as so: db_1row get_task_values { } template::element set_value form_name estimated_hours_work $estimated_hours_work Troubleshooting A good way to troubleshoot when you're using ad_form is to add the following code at the top of the .tcl page (thanks Jerry Asher): ns_log notice it's my page! set mypage [ns_getform] if {$mypage eq ""} { ns_log notice no form was submitted on my page } else { ns_log notice the following form was submitted on my page ns_set print $mypage } Tips for form widgets Here are some tips for dealing with some of the form widgets: Current widget Common Errors Here are some common errors and what to do when you encounter them: Error when selecting values This generally happens when there is an error in your query.