Thank you very much for providing the code and help!
I will try it some time later.
I have used Struts, Spring Web, JSF for a few years. I only recently
discovered Click and fell for it. It is so clean and simple and yet comes
pre-built production-quality controls (Date picker, table, etc.).
For complicated use cases, I can take full power of server side java coding
instead of dealing with complicated and verbose tags (JSP, JSF). What is
even better is the advantage of java inheritance. I used the inheritance for
code reuse which also greatly simplifies the java code.
florin.g wrote:
>
> Take a look at this and let me know what you think. You might want to
> tweak it to your taste yet it does the job. It does keep both option
> elements in synch with each other and with the table navigation.
>
> It does not appear that this use case should be implemented by the
> framework - it should be up to the developer regardless of the framework.
>
> While it can handle page state, Click tends to be stateless in most cases.
> This is why this example is made with no page state. The interesting
> points are in the onInit() method where you keep track of the state of the
> option elements with the option.setValue() method; you also keep track of
> the option elements when you click on the table navigation via the
> table.getControlLink().setParameter() method.
>
> The "state" and "district" object attributes are populated at each request
> by the framework, considering them as http request parameters (as I
> understand this).
>
> I've never needed this scenario before so I guess it can be done better.
>
> <pre style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
> 1 package pages;/**
> 2 * User: florin
> 3 * Date: Feb 3, 2009
> 4 * Time: 10:40:10 PM
> 5 */
> 6
> 7 import net.sf.click.ActionListener;
> 8 import net.sf.click.Control;
> 9 import net.sf.click.Page;
> 10 import net.sf.click.control.*;
> 11 import net.sf.click.extras.control.TableInlinePaginator;
> 12 import org.apache.log4j.Logger;
> 13
> 14 import java.util.ArrayList;
> 15 import java.util.HashMap;
> 16 import java.util.List;
> 17 import java.util.Map;
> 18
> 19 public class StatefulChoice extends Page {
> 20 static Logger logger = Logger.getLogger(StatefulChoice.class);
> 21
> 22 //-- keeps track of the currently selected state and district
> 23 //-- the state and district will be attached to the table
> paginator
> 24 //-- the state and district will be used to keep the state of the
> option values
> 25 public String state;
> 26 public String district;
> 27
> 28
> 29 private Select states = new Select("state");
> 30 private Select districts = new Select("district");
> 31
> 32 public Form form = new Form("form");
> 33 public Table schTable = new Table("schools");
> 34
> 35 public StatefulChoice() {
> 36 //-- I use a submit as a temporary hack as this is not part
> of the questioin, the submit button is invisible
> 37 //-- As an alternative, javascript can replace the
> functionality of the form, such as resubmitting the page
> 38 //-- with newly attached parameters (state and
> district)
> 39 Submit submit = new Submit("Submit");
> 40 submit.setStyle("visibility", "hidden");
> 41 submit.setActionListener(new ActionListener() {
> 42 public boolean onAction(Control source) {
> 43 return onSubmit();
> 44 }
> 45 });
> 46 form.add(submit);
> 47
> 48 //-- both options will cause the submit button to execute
> 49 states.setAttribute("onchange",
> "document.getElementById('form_Submit').click()");
> 50 form.add(states);
> 51
> 52 //-- add schools table
> 53 schTable.setClass(Table.CLASS_SIMPLE);
> 54 schTable.setHoverRows(true);
> 55 schTable.setPageSize(3);
> 56 schTable.setShowBanner(true);
> 57 schTable.setSortable(true);
> 58 schTable.setPaginator(new TableInlinePaginator(schTable));
> 59 schTable.setPaginatorAttachment(Table.PAGINATOR_INLINE);
> 60
> 61 Column name = new Column("name", "School
> Name");
> 62 schTable.addColumn(name);
> 63 schTable.addColumn(new Column("city"));
> 64 schTable.addColumn(new Column("state"));
> 65 }
> 66
> 67 public void onInit() {
> 68 logger.debug("onInit, state=" + state);
> 69
> 70 //-- this for statement will be replaced by your helper
> classes
> 71 for (int i = 0; i < _states.length; i++) {
> 72 states.add(new Option(_states[i], _states[++i]));
> 73 }
> 74
> 75 //-- this is key
> 76 if (state != null) {
> 77 //-- set the "selected" option value, keeps its
> state
> 78 states.setValue(state);
> 79 //-- based on selected state, populate the subselect
> 80 //-- you may choose to have the subselect be visible at
> all times
> 81 form.add(getDistricts());
> 82 }
> 83
> 84 if (district != null) {
> 85 //-- attach the option values to the table pagination
> 86 schTable.getControlLink().setParameter("state",
> state);
> 87
> schTable.getControlLink().setParameter("district", district);
> 88 //-- set the state of the districts option element in the
> page
> 89 districts.setValue(district);
> 90 addStuffToTable();
> 91 }
> 92
> 93 }
> 94
> 95 public Control getSchools() {
> 96 return null;
> 97 }
> 98
> 99 //-- temporary method, use your own datasource
> 100 public Select getDistricts() {
> 101 //-- submit the invisible submit button of the form; see
> notes above
> 102 districts.setAttribute("onchange",
> "document.getElementById('form_Submit').click()");
> 103 districts.add(new Option("", "Please Select
> District"));
> 104
> 105 // Take your districts from an outside source, the following
> is just a temporary hack;
> 106 if ("GA".equalsIgnoreCase(state)) {
> 107 String[] _distrs = _d[0];
> 108 for (int i = 0; i < _distrs.length; i++) {
> 109 districts.add(new Option(_distrs[i], _distrs[++i]));
> 110 }
> 111 } else if ("CA".equalsIgnoreCase(state)) {
> 112 String[] _distrs = _d[1];
> 113 for (int i = 0; i < _distrs.length; i++) {
> 114 districts.add(new Option(_distrs[i], _distrs[++i]));
> 115 }
> 116 } else if ("NY".equalsIgnoreCase(state)) {
> 117 String[] _distrs = _d[2];
> 118 for (int i = 0; i < _distrs.length; i++) {
> 119 districts.add(new Option(_distrs[i], _distrs[++i]));
> 120 }
> 121 }
> 122
> 123 return districts;
> 124 }
> 125
> 126
> 127 public boolean onSubmit() {
> 128 logger.debug("Selected State: " + state);
> 129 logger.debug("Selected District: " + district);
> 130 System.out.println("StatefulChoice.onSubmit " +
> form);
> 131 //-- do conditional work, only when school is selected
> 132 return true;
> 133 }
> 134
> 135
> 136 private static String[] _states = {"", "Please
> Select State", "GA", "Georgia", "CA",
> "California", "NY", "New York"};
> 137
> 138
> 139 private static String[][] _d = {
> 140 {"GA_EA", "GA East District",
> "GA_SO", "GA South District"},
> 141 {"CA_OR", "Orange County",
> "CA_AL", "Alameda"},
> 142 {"NY_BR", "Bronx District",
> "NY_MH", "Manhattan Slums", "NY_QN",
> "Queens Wideland"}
> 143 };
> 144
> 145 //-- this is temporary garbage
> 146 public void addStuffToTable() {
> 147 if ("GA".equalsIgnoreCase(state)) {
> 148 if ("GA_EA".equalsIgnoreCase(district)) {
> 149 List<Map> list = new ArrayList<Map>();
> 150 HashMap<String, String> map = new
> HashMap<String, String>(7);
> 151 map.put("name", "School One");
> 152 map.put("city", "City One");
> 153 map.put("state", "GA");
> 154 list.add(map);
> 155
> 156 map = new HashMap<String, String>(7);
> 157 map.put("name", "School 2");
> 158 map.put("city", "City 2");
> 159 map.put("state", "GA");
> 160 list.add(map);
> 161 map = new HashMap<String, String>(7);
> 162 map.put("name", "School 3");
> 163 map.put("city", "City 3");
> 164 map.put("state", "GA");
> 165 list.add(map);
> 166 map = new HashMap<String, String>(7);
> 167 map.put("name", "School 4");
> 168 map.put("city", "City 4");
> 169 map.put("state", "GA");
> 170 list.add(map);
> 171 map = new HashMap<String, String>(7);
> 172 map.put("name", "School 5");
> 173 map.put("city", "City 5");
> 174 map.put("state", "GA");
> 175 list.add(map);
> 176 map = new HashMap<String, String>(7);
> 177 map.put("name", "School 6");
> 178 map.put("city", "City 6");
> 179 map.put("state", "GA");
> 180 list.add(map);
> 181 map = new HashMap<String, String>(7);
> 182 map.put("name", "School 7");
> 183 map.put("city", "City 7");
> 184 map.put("state", "GA");
> 185 list.add(map);
> 186
> 187 schTable.setRowList(list);
> 188 }
> 189 }
> 190
> 191 if ("CA".equalsIgnoreCase(state)) {
> 192 if ("CA_AL".equalsIgnoreCase(district)) {
> 193 List<Map> list = new ArrayList<Map>();
> 194 HashMap<String, String> map = new
> HashMap<String, String>(7);
> 195 map.put("name", "1 school");
> 196 map.put("city", "1 city");
> 197 map.put("state", "ca");
> 198 list.add(map);
> 199
> 200 map = new HashMap<String, String>(7);
> 201 map.put("name", "2 School 2");
> 202 map.put("city", "2 City 2");
> 203 map.put("state", "CA");
> 204 list.add(map);
> 205 map = new HashMap<String, String>(7);
> 206 map.put("name", "3 School 3");
> 207 map.put("city", "3 City 3");
> 208 map.put("state", "CA");
> 209 list.add(map);
> 210 map = new HashMap<String, String>(7);
> 211 map.put("name", "4 School 4");
> 212 map.put("city", "4 City 4");
> 213 map.put("state", "CA");
> 214 list.add(map);
> 215 map = new HashMap<String, String>(7);
> 216 map.put("name", "5 School 5");
> 217 map.put("city", "5 City 5");
> 218 map.put("state", "CA");
> 219 list.add(map);
> 220 map = new HashMap<String, String>(7);
> 221 map.put("name", "6 School 6");
> 222 map.put("city", "6 City 6");
> 223 map.put("state", "CA");
> 224 list.add(map);
> 225 map = new HashMap<String, String>(7);
> 226 map.put("name", "7 School 7");
> 227 map.put("city", "7 City 7");
> 228 map.put("state", "CA");
> 229 list.add(map);
> 230
> 231 schTable.setRowList(list);
> 232 }
> 233 }
> 234 }
> 235 }
> 236
> 237
> </pre>
>
> ----------------------------------------------------------------------------------------
> AND THE TEMPLATE PAGE
> ----------------------------------------------------------------------------------------
>
> <pre style="color: rgb(0,0,0); font-weight: normal; font-style: normal; ">
> 3 <html>
> 4 <head>
> 5 <title>Stateful Choice</title>
> 6 $imports
> 7
> 8 </head>
> 9 <body>
> 10 <!-- again, if not a form, you can use client side javascript
> to update server page with option data -->
> 11 $form
> 12 $schools
> 13
> 14 </body>
> 15 </html>
> </pre>
>
>
>
>
>
>
> Jay Wang wrote:
>>
>> Thanks you all for the help!
>> I found it hard to implement and decided to let go the paging and sorting
>> of my table. This way I have no issue. My page size typically is less
>> than 200. I am good for now.
>> Jay Wang.
>>
>>
>> florin.g wrote:
>>>
>>> I looks like I needed to know this myself:
>>>
>>> table.getControlLink().setParameter("companyId", companyId);
>>>
>>> For this case, it is the way to go.
>>>
>>>
>>>
>>> sabob wrote:
>>>>
>>>> Hi Jay,
>>>>
>>>> As Florin suggested you can use a stateful Page, or add the state and
>>>> district parameters to the Table controlLink.
>>>>
>>>> See here for details:
>>>> http://incubator.apache.org/click/docs/click-api/net/sf/click/control/Table.html#paging-and-sorting
>>>>
>>>> Another option is to store the Page state in the session for example:
>>>>
>>>> public class SchoolPageState implements Serializable {
>>>> public String state;
>>>> public String district;
>>>> }
>>>>
>>>> public class Schools extends WebSiteTemplate {
>>>> public void onInit() {
>>>> super.onInit();
>>>> restoreState();
>>>> ...
>>>> }
>>>>
>>>> public void saveState() {
>>>> // store the state in the session
>>>> }
>>>>
>>>> public void restoreState() {
>>>> // retrieve the state from the session
>>>> }
>>>>
>>>> public void onRender() {
>>>> saveState();
>>>> }
>>>> }
>>>>
>>>> kind regards
>>>>
>>>> bob
>>>>
>>>>
>>>> florin.g wrote:
>>>>> By default, your page is stateless - hence your selections are lost as
>>>>> you
>>>>> navigate the table for the first time.
>>>>>
>>>>> You need to either use a stateful page [ setStateful(true) in the page
>>>>> constructor ] or do some footwork with the url parameters.
>>>>>
>>>>> To continue use a stateless page, you need to pass the choices made in
>>>>> your
>>>>> lists as url parameters back to the page when you set the district and
>>>>> then
>>>>> when you navigate the table. I'd use a client side library such as
>>>>> jQuery to
>>>>> capture the values of the select objects and append these values to
>>>>> the
>>>>> previous/next table navigation urls. When back to the page, you must
>>>>> use
>>>>> those values to re-configure your lists (state, district and schools).
>>>>> Sounds like a lot of work. Go with the stateful page.
>>>>>
>>>>>
>>>>>
>>>>> Jay Wang wrote:
>>>>>
>>>>>> Hi,
>>>>>> I have a page where I let user to select a state from a selection
>>>>>> list of
>>>>>> 50 states and after the selection, a school district selection is
>>>>>> populated based on the state selected. The user then proceeds to
>>>>>> select a
>>>>>> school district. After a district is selected , a table display of
>>>>>> schools
>>>>>> from that district is shown which should allow user to page through
>>>>>> if
>>>>>> there are multiple pages. The problem I ran into is that the paging
>>>>>> and
>>>>>> sorting of table columns does not work and it also messes up the
>>>>>> selection
>>>>>> as well.
>>>>>> Source code is attached here (Schools.java and school.htm
>>>>>>
>>>>>> Schools.java
>>>>>> ------------------------
>>>>>> import java.sql.SQLException;
>>>>>> import java.util.List;
>>>>>> import net.sf.click.control.Column;
>>>>>> import net.sf.click.control.Form;
>>>>>> import net.sf.click.control.PageLink;
>>>>>> import net.sf.click.control.Select;
>>>>>> import net.sf.click.control.Table;
>>>>>> import net.sf.click.extras.control.LinkDecorator;
>>>>>> import net.sf.click.extras.control.TableInlinePaginator;
>>>>>> import org.apache.commons.lang.StringUtils;
>>>>>> import us.myschoolusa.entity.School;
>>>>>> import us.myschoolusa.service.DataManager;
>>>>>> import us.myschoolusa.util.Helper;
>>>>>>
>>>>>> /**
>>>>>> *
>>>>>> * @author wangj6
>>>>>> */
>>>>>> public class Schools extends WebSiteTemplate {
>>>>>>
>>>>>> public Table schTable;
>>>>>> public PageLink viewLink;
>>>>>> public School school;
>>>>>> public Form form;
>>>>>> private Select stateSelect;
>>>>>> private Select districtSelect;
>>>>>>
>>>>>> public Schools() {
>>>>>>
>>>>>>
>>>>>> form = new Form("selectForm");
>>>>>>
>>>>>>
>>>>>> stateSelect = new Select("state", "");
>>>>>> stateSelect.setAttribute("onchange",
>>>>>> "handleChange('selectForm_district', selectForm)");
>>>>>> form.add(stateSelect);
>>>>>>
>>>>>> districtSelect = new Select("district", "");
>>>>>> districtSelect.setAttribute("onchange",
>>>>>> "selectForm.submit()");
>>>>>> form.add(districtSelect);
>>>>>>
>>>>>> schTable = new Table("schTable");
>>>>>>
>>>>>> schTable.setClass(Table.CLASS_SIMPLE);
>>>>>> schTable.setHoverRows(true);
>>>>>> schTable.setPageSize(25);
>>>>>> schTable.setShowBanner(true);
>>>>>> schTable.setSortable(true);
>>>>>> schTable.setPaginator(new TableInlinePaginator(schTable));
>>>>>> schTable.setPaginatorAttachment(Table.PAGINATOR_INLINE);
>>>>>>
>>>>>> Column name = new Column("fullName", "School Name");
>>>>>> schTable.addColumn(name);
>>>>>> schTable.addColumn(new Column("city"));
>>>>>> schTable.addColumn(new Column("state"));
>>>>>> Column action = new Column("Action", "");
>>>>>> viewLink = new PageLink("view", SchoolDetail.class);
>>>>>> viewLink.setParameter("referrer", "/schools.htm");
>>>>>> action.setDecorator(new LinkDecorator(schTable, viewLink,
>>>>>> "schoolId"));
>>>>>> action.setSortable(false);
>>>>>> schTable.addColumn(action);
>>>>>> }
>>>>>>
>>>>>> public void onInit(){
>>>>>> super.onInit();
>>>>>> populateSelect();
>>>>>>
>>>>>> }
>>>>>>
>>>>>> private void populateSelect() {
>>>>>>
>>>>>> try {
>>>>>> stateSelect.setOptionList(Helper.getOptionForStates());
>>>>>> } catch (SQLException e) {
>>>>>> e.printStackTrace();
>>>>>> form.setError("error.");
>>>>>> }
>>>>>>
>>>>>> stateSelect.bindRequestValue();
>>>>>>
>>>>>> if (StringUtils.isEmpty(stateSelect.getValue())) {
>>>>>> // No state selected, exit early
>>>>>> return;
>>>>>> }
>>>>>> try {
>>>>>>
>>>>>>
>>>>>> districtSelect.setOptionList(Helper.getOptionForDistrictsByState(stateSelect.getValue()));
>>>>>> districtSelect.bindRequestValue();
>>>>>> if (StringUtils.isEmpty(districtSelect.getValue())) {
>>>>>> // No district selected, exit early
>>>>>> return;
>>>>>> }
>>>>>> List<School> schList =
>>>>>> DataManager.selectSchoolsByDistrictId(Integer.parseInt(districtSelect.getValue()));
>>>>>> schTable.setRowList(schList);
>>>>>>
>>>>>> } catch (SQLException e) {
>>>>>> e.printStackTrace();
>>>>>> }
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> schools.htm
>>>>>> ----------------------------------
>>>>>> <h2>School Directory</h2>
>>>>>> <br/>
>>>>>> $selectForm<br/>
>>>>>> #if (${schTable.getRowList().size()} > 0)
>>>>>> $schTable
>>>>>> #end
>>>>>> <script type="text/javascript">
>>>>>> function handleChange(id, form) {
>>>>>> var select=document.getElementById(id);
>>>>>> if(select != null) {
>>>>>> select.selectedIndex=-1;
>>>>>> }
>>>>>> form.submit();
>>>>>> }
>>>>>> </script>
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>>
>>>
>>>
>>
>>
>
>
--
View this message in context:
http://n2.nabble.com/need-help-on-select-and-table-controls-tp2222256p2277111.html
Sent from the click-user mailing list archive at Nabble.com.