Problem Solution Discussion Creating Multiple-Pick Form Elements from Database Content

c:set var=dateList value={rs.rowsByIndex[0]} c:forEach var=date items={dateList} input type=radio name=date value=c:out value={date} c:out value={date} br c:forEach Of course, if your API m akes it reasonably easy t o perform dat e calculat ions, it likely will be m ore efficient t o generat e t he list of dat es on t he client side wit hout sending a query t o t he MySQL server.

18.4 Creating Multiple-Pick Form Elements from Database Content

18.4.1 Problem

A form needs t o present a field t hat offers t he user a set of opt ions and allows any num ber of t hem t o be select ed.

18.4.2 Solution

Use a m ult iple-pick list elem ent , such as a set of checkboxes or a scrolling list .

18.4.3 Discussion

Mult iple-pick form elem ent s allow you t o present m ult iple choices, any num ber of which can be select ed, or possibly even none of t hem . For our exam ple scenario in which cust om ers order cow figurines online, t he m ult iple-pick elem ent is represent ed by t he set of accessory it em s t hat are available. The accessory colum n in t he cow_order t able is represent ed as a SET , so t he allowable and default values can be obt ained from t he following query: mysql SHOW COLUMNS FROM cow_order LIKE accessories\G 1. row Field: accessories Type: setcow bell,horns,nose ring,tail ribbon Null: YES Key: Default: cow bell,horns Extra: This set of it em s can reasonably be represent ed as eit her a set of checkboxes or as a m ult iple- pick scrolling list . I n bot h cases, t he cow bell and horns it em s should be select ed init ially, because each is present in t he colum ns default value. I will discuss t he HTML synt ax for t hese elem ent s, t hen show how t o generat e t hem from wit hin script s. The m at erial in t his sect ion relies heavily on Recipe 18.3 , which discusses radio but t ons, pop- up m enus, and single-pick scrolling list s. I assum e youve already read t hat sect ion. • Ch e ck box e s A group of checkboxes is sim ilar t o a group of radio but t ons in t hat it consist s of input elem ent s t hat all have t he sam e name at t ribut e. However, t he type at t ribut e is checkbox rat her t han radio , and you can specify checked for as m any it em s in t he group as you want t o be select ed by default . I f no it em s are m arked as checked , none are select ed init ially. The following checkbox set shows t he cow accessory it em s wit h t he first t wo it em s select ed by default : input type=checkbox name=accessories value=cow bell checked=checked cow bell input type=checkbox name=accessories value=horns checked=checked horns input type=checkbox name=accessories value=nose ring nose ring input type=checkbox name=accessories value=tail ribbon tail ribbon • CScr ollin g list A m ult iple- pick scrolling list is const ruct ed in m uch t he sam e m anner as it s single-pick count erpart . The differences are t hat you include a multiple at t ribut e in t he opening select t ag, and t he default value behavior is different . For a single- pick list , you can add selected t o at m ost one it em , and t he first it em is select ed by default in t he absence of an explicit selected at t ribut e. Wit h a m ult iple-pick list , you can add a selected at t ribut e t o as m any of t he it em s as you like, and no it em s are select ed by default in t he absence of selected at t ribut es. I f t he set of cow accessories is represent ed as a m ult iple-pick scrolling list wit h cow bell and horns select ed init ially, it looks like t his: select name=accessories size=3 multiple=multiple option value=cow bell selected=selectedcow belloption option value=horns selected=selectedhornsoption option value=nose ringnose ringoption option value=tail ribbontail ribbonoption select I n CGI .pm - based Perl script s, you creat e checkbox set s or scrolling list s by invoking checkbox_group or scrolling_list . These funct ions t ake name , values , labels , and default argum ent s, j ust like t heir single- pick cousins. But because m ult iple it em s can be select ed init ially, CGI .pm allows t he default ar gum ent t o be specified as eit her a scalar value or a reference t o an array of values. I t also accept s t he argum ent nam e defaults as a synonym for default . To get t he list of legal values for a SET colum n, w e can do t he sam e t hing as in Recipe 18.3 for ENUM colum ns—t hat is, call a ut ilit y rout ine t hat ret urns t he colum n m et adat a: my acc_info = get_enumorset_info dbh, cow_order, accessories; However, t he default value for a SET colum n is not in a form t hat is direct ly usable for form elem ent generat ion. MySQL represent s SET default values as a com m a- separat ed list of it em s. For exam ple, t he default for t he accessories colum n is cow bell,horns . That doesnt m at ch t he list - of- values form at t hat t he CGI .pm funct ions expect , so it s necessary t o split t he default value at t he com m as t o obt ain an array. The following expression shows how t o do so, t aking int o account t he possibilit y t hat t he default value m ight be undef NULL : my acc_def = defined acc_info-{default} ? split ,, acc_info-{default} : ; Aft er split t ing t he default value, pass t he result ing array by reference t o whichever of t he list - generat ing funct ions you want t o use: print checkbox_group -name = accessories, -values = acc_info-{values}, -default = \acc_def, -linebreak = 1; display buttons vertically print scrolling_list -name = accessories, -values = acc_info-{values}, -default = \acc_def, -size = 3, display 3 items at a time -multiple = 1; create multiple-pick list When you use SET values like t his t o creat e list elem ent s, t he values are displayed in t he order t hey are list ed in t he colum n definit ion. That m ay not correspond t o t he order in which you want t hem t o appear; if not , sort t he values appropriat ely. For PHP and Pyt hon, we can creat e ut ilit y funct ions t o generat e m ult iple- pick it em s. Theyll have t he following invocat ion synt ax: make_checkbox_group name, values, labels, default, vertical make_scrolling_list name, values, labels, default, size, multiple The name , values , and labels argum ent s t o t hese funct ions are sim ilar t o t hose of t he PHP and Pyt hon single-pick ut ilit y rout ines described in Recipe 18.3 . make_checkbox_group t ak es a vertical argum ent t hat indicat es t hat t he it em s should be st acked vert ically rat her t han horizont ally if it s t rue. make_scrolling_list has already been described in Recipe 18.3 for producing single-pick list s; t o use it here, t he multiple argum ent should be t rue t o produce a m ult iple-pick list . For bot h funct ions, t he default argum ent can be an array of m ult iple values if several it em s should be select ed init ially. make_checkbox_group looks like t his shown here in Pyt hon; t he PHP version is sim ilar : def make_checkbox_group name, values, labels, default, vertical: if type values not in types.ListType, types.TupleType: return make_checkbox_group: values argument must be a list if type labels not in types.ListType, types.TupleType: return make_checkbox_group: labels argument must be a list if len values = len labels: return make_checkbox_group: value and label list size mismatch if type default not in types.ListType, types.TupleType: default = [ default ] convert scalar to list str = for i in range len values: value = values[i] label = labels[i] make sure value and label are strings if type value is not types.StringType: value = `value` if type label is not types.StringType: label = `label` select the item if it corresponds to one of the default values checked = for d in default: if type d is not types.StringType: d = `d` if value == d: checked = checked=\checked\ break if type name is not types.StringType: name = `name` str = str + \ input type=\checkbox\ name=\s\ value=\s\s s \ cgi.escape name, 1, cgi.escape value, 1, checked, cgi.escape label, 1 if vertical: str = str + br display items vertically str = str + \n return str To fet ch t he cow accessory inform at ion and present it using checkboxes, do t his: import re needed for re.split acc_info = get_enumorset_info conn, cow_order, accessories if acc_info[default] == None: acc_def = else: acc_def = re.split ,, acc_info[default] print make_checkbox_group accessories, acc_info[values], acc_info[values], acc_def, 1 display items vertically To display a scrolling list inst ead, invoke make_scrolling_list : print make_scrolling_list accessories, acc_info[values], acc_info[values], acc_def, 3, display 3 items at a time 1 create multiple-pick list I n PHP, fet ch t he accessory inform at ion, t hen present checkboxes or a scrolling list as follows: acc_info = get_enumorset_info conn_id, cow_order, accessories; acc_def = explode ,, acc_info[default]; print make_checkbox_group accessories[ ], acc_info[values], acc_info[values], acc_def, TRUE; display items vertically print make_scrolling_list accessories[ ], acc_info[values], acc_info[values], acc_def, 3, display 3 items at a time TRUE; create multiple-pick list Not e t hat t he field nam e in t he PHP exam ples is specified as accessories[ ] r at her t han as accessories . I n PHP, you m ust add [ ] t o t he nam e if you w ant t o allow a field t o have m ult iple values. I f you om it t he [ ] , t he user w ill be able t o select m ult iple it em s while filling in t he form , but PHP will ret urn only one of t hem t o your script . This issue will com e up again when we discuss how t o process t he cont ent s of subm it t ed form s in Recipe 18.6 . I n JSP pages, t he getEnumOrSetValues funct ion used earlier t o get t he value list for t he size colum n an ENUM can also be used for t he accessory colum n a SET . The colum n definit ion and default value are in t he second and fift h colum n of t he SHOW COLUMNS query t hat ret urns inform at ion about t he accessory colum n. Run t he query, parse t he t ype definit ion int o a list of values nam ed values , and put t he default value in defList like t his: sql:query var=rs dataSource={conn} SHOW COLUMNS FROM cow_order LIKE accessories sql:query c:set var=typeDef scope=page value={rs.rowsByIndex[0][1]} getEnumOrSetValues pageContext, typeDef, values; c:set var=defList scope=page value={rs.rowsByIndex[0][4]} For a SET colum n, t he defList value m ight cont ain m ult iple values, separat ed by com m as. I t needs no special t reat m ent ; t he JSTL c:forEach t ag knows how t o it erat e over such a st ring, so t he default values for a checkbox set can be init ialized as follow s: c:forEach var=val items={values} input type=checkbox name=accessories value=c:out value={val} c:forEach var=default items={defList} c:if test={val == default}checked=checkedc:if c:forEach c:out value={val} br c:forEach For a m ult iple-pick scrolling list , do t his: select name=accessories size=3 multiple=multiple c:forEach var=val items={values} option value=c:out value={val} c:forEach var=default items={defList} c:if test={val == default}selected=selectedc:if c:forEach c:out value={val} option c:forEach select

18.5 Loading a Database Record into a Form