Forum OpenACS Q&A: select list populated from db and form templates

Hello, I'm having trouble working out how to do something which seems like it should be simple. I have a select list which is populated via a form template to the names of people in a db. I got the names from a db_list_of_list query and pass them to the form template which very nicely behind the scenes sets the value of the select option to the persons id and makes the persons name visible in the select list. The code is something like this:
        
#form template        
... set person_names [db_list_of_lists person_names_qry {        
			f_name  || ' ' || lname as name,        
			person_id        
			from person; ]]        
        
... template::element create person_form person_names -label "names"        
select -datatype text -options $person_names        
        
      
# this creates the form something like this:        
  < select name="person_names" > 
  < option value="3" selected="selected" > some name </ option 
> 
  < option value="18" > some other name </ option > 
</ select >      
 
That's all fine but I'm now having trouble working out how to get hold of the option value of the name chosen by the user from the drop down list, i.e. if they choose the first I want to grab the value 3 in the above example. Can it be done easily or am I going about it the wrong way. Any ideas gratefully received. Cheers Adam
Collapse
Posted by Jun Yamog on
I believe you can get the person_names by putting it to ad_page_contract where the form submits.  You may also want to use ad_form which is a wrapper around the template::*.
Adam,

The value of the form element will be passed to the page specified int he forms ACTION attribute. You need to specify the variables you want to use in ad_page_contract in the target page.

The variable name is the same as the name of the form element you created. So your taget page would look like this:

ad_page_contract {
     desription of my page
} {
     person_names
     other_var_name
     ...
}
After ad_page_contract person_names would be set to the value of the item that was selected.
Thanks for the answers but I think I was a bit unclear about what
I'm trying to do. I'm not trying to get the name that was submitted
but the option value, so in my example if "some name" is chosen I
want to be able to pull in the corresponding integer option value,
in this case 3 which is the key that I will search the db on.

I already have the identifier person_id as a property defined on the
form but how to I grab the selection value, not tag contents and put
it in the person_id var?
Thanks
Adam

Adam,

The VALUE of the form element will be whatever is sepcified for the value attribute of the option that is selected. From the code you posted, the values are correct in the HTML code. All you need to do is used ad_page_contract which takes the query variables passed by the browser and sets Tcl variables with the same names in your Tcl page.

Please note, which you called the form element "person_names" the code you show has the value as the person_id of the person for each selection, not their name. The name is used for display in the select box only.

Using a select widget is fine if you don't expect to have many users. If you do, I would use something like the following which generates a text widget where the name can be entered:
template::element create person_form person_id
    -widget search
    -datatype search
    -label {Name}
    -search_query {
        select last_name||','||first_names, person_id
        from persons
        where last_name||','||first_names like :value} 
    -value $person_id
Note that :value is defined by the interface and must remain the same. The form will expect you to enter last,first in my example.

The page contract has {person_id {}} for this element/variable.

There is only one bug in this that I know of: If some part of the form doesn't validate, all -search datatype elements' numeric values are displayed instead of being translated back to the person's name via the -search_query. This datatype is a really cool, but the implementation is not quite there.

Note I use 'like' instead of =, which allows a user to type 'lastname%'. If the -search_query returns returns multiple rows, this widget presents a select box from them.