<?xml version='1.0' ?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
               "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
<!ENTITY % myvars SYSTEM "../variables.ent">
%myvars;
]>
<sect1 id="form-builder">
<title>Using Form Builder: building html forms dynamically</title>


<sect2 id="ad-form-overview">
<title>Overview</title>
<authorblurb>
  <para><phrase role="cvstag">($Id: form-builder.xml,v 1.8 2006/07/17 05:38:37 torbenb Exp $)</phrase></para>
</authorblurb>
<para>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 <ulink
 url="http://openacs.org/api-doc/proc-view?proc=ad_form">api
 documentation</ulink> is helpful.</para>

</sect2>

  <sect2 id="multi-part-elements">
    <title>Multi-part Elements</title>
    <para>Some elements have more than one choice, or can submit more than one value.</para>
    <sect3>
      <title>SELECT elements</title>
      <orderedlist>
        <listitem>
          <formalpara>
            <title>Creating the form element</title>
            <para>Populate a list of lists with values for the option list.</para>
          </formalpara>
          <programlisting>set foo_options [db_list_of_lists foo_option_list "
    select foo,
           foo_id
      from foos
"]
</programlisting>
          <para>The variable <computeroutput>foo_options</computeroutput> should resemble <computeroutput>{{first foo} 1234} {{second foo} 1235}
</computeroutput></para>
          <para>Within ad_form, set up the element to use this list:</para>
          <programlisting>{foo:text(select)
        {label "Which Foo"}
        {options $foo_options}
    }</programlisting>
          <para>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 <computeroutput>-new_data</computeroutput> and <computeroutput>-edit_data</computeroutput>.  In the example, it is available as <computeroutput>$foo</computeroutput></para>
        </listitem>
      </orderedlist>
        <para>See also the 
        <ulink url="http://www.w3.org/TR/html401/interact/forms.html#h-17.6">W3C spec for "The SELECT, OPTGROUP, and OPTION elements"</ulink>.
        </para>
    </sect3>
  </sect2>

  <sect2 id="refreshing">
    <title>Using refreshes to pull additional information from the
    database</title>
    <para>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</para>

    <programlisting>    {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}
    }
    </programlisting>

    <para>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:
    </para>
    <programlisting>    if {[exists_and_not_null pm_task_id]} {
    db_1row get_task_values { }
    ad_form -extend -name form_name -form { ... }
    </programlisting>
    
    <para>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:</para>

    <programlisting>    db_1row get_task_values { }
    template::element set_value form_name estimated_hours_work $estimated_hours_work
    </programlisting>

  </sect2>

  <sect2 id="form-troubleshooting">
    <title>Troubleshooting</title>
    <para>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):</para>

    <programlisting>
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
}
    </programlisting>
  </sect2>

  <sect2 id="form-widgets">
    <title>Tips for form widgets</title>
    <para>Here are some tips for dealing with some of the form widgets:</para>

    <para><ulink url="http://openacs.org/forums/message-view?message_id=106331">Current widget</ulink></para>

  </sect2>

  <sect2 id="errors">
    <title>Common Errors</title>
    <para>Here are some common errors and what to do when you
    encounter them:</para>
    <sect3>
      <title>Error when selecting values</title>
          <para>This generally happens when there is an error in your
          query.</para>
    </sect3>
  </sect2>

</sect1>
