Prev | Chapter 10. Development Reference | Next

## Using Form Builder: building html forms dynamically

### Overview

($Id: form-builder.html,v 1.24.2.3 2009/09/11 23:41:26 donb Exp $)
OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff.

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

1. 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 {[exists_and_not_null pm_task_id]} {
        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 {[string equal "" $mypage]} {
        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.

Prev | Home | Next
Programming with AOLserver | Up | Chapter 11. Engineering Standards

View comments on this page at openacs.org