Forgot to mention that Hidden fields need extra care because they get lost in the redirect that follows a server-side validation failure. This show how to work around the problem with FLASH persistence:
* http://jumpstart.doublenegative.com.au/jumpstart/examples/input/totalcontroledit1/1 Geoff On 01/01/2013, at 7:19 PM, Geoff Callender wrote: > Agreed. To avoid thinking about the sequence of getters, set up the form in > onPrepareForRender(). > > Eg. > http://jumpstart.doublenegative.com.au/jumpstart/examples/select/easyobject > > As for the ValueEncoder do you need it? > > Eg. > http://jumpstart.doublenegative.com.au/jumpstart/examples/select/id/1 > > On submit, there are many ways to get the chosen user, and each one has a > cost. Off the top of my head, they include: > > * cache the list client-side as a t:hidden in the form. You'll need an > encoder that can encode/decode the whole list to/from a String. > > * cache the list client-side as a cookie. Probably not a good use of > cookies. > > * cache the list server-side in the session. If you don't mind the > overhead of a session then consider this: > > > http://jumpstart.doublenegative.com.au/jumpstart/examples/state/storingdatainapage > > * cache the list server-side in a conversation. See: > > > http://jumpstart.doublenegative.com.au/jumpstart/examples/wizard/usingformfragments/START/wiz1 > > * cache the list in the business tier. For how long? When should it be > refreshed? memcache? ehcache? > > * no cache, get the user by id from the database. If the user has been > updated by someone else you know immediately. > > Your encoder is doing the last one, and it seems like a pretty good way to > start. IMHO, I'd avoid caching unless the use case demands it, or until the > simpler solution is demonstrated to be causing a problem. > > Geoff > > On 31/12/2012, at 10:46 PM, Chris Poulsen wrote: > >> Hi, >> >> To me this looks like your problem is that you have a getters with >> side-effects? ( getUsers() for example ). >> >> What if you set up your page-instance variables prior to rendering (not >> during - take a look at page lifecycle phases), then you could determine >> your blank option and retrieve/cache your user list without having "order" >> issues. >> >> If I'm not mistaken about the ValueEncoder i think it is not used while you >> actually have the user list fetched (during initial page-render), but when >> you choose to act on some user object. Its id is passed along to the page >> and the encoder kicks in to provide you with a fully configured UserBean. >> So the UserBean fetches basically happens during two different requests, >> and probably only on the object(s) that you actually choose to do something >> with. >> - Of course you can cache the user list in session or similar and have it >> available for later use, but I do not really like that option. >> >> -- >> Chris >> >> >> On Mon, Dec 31, 2012 at 9:24 AM, John <j...@quivinco.com> wrote: >> >>> consider the following example >>> >>> When the select component is rendered the call to getUOption precedes the >>> call to getUserSelectModel so the uOption state is not yet set. >>> >>> <form t:type="form" t:id="form"> >>> <t:errors /> >>> <t:zone t:id="userZone" id="userZone"> >>> <t:select t:id="user" t:blankOption="prop:uOption" >>> t:model="userSelectModel" >>> t:encoder="userEncoder" t:value="selectedUserId" t:zone="userZone" /> >>> >>> public BlankOption getUOption() { >>> return uOption? BlankOption.ALWAYS:BlankOption.NEVER; >>> } >>> >>> public SelectModel getUserSelectModel() { >>> return selectModelFactory.create(getUsers(), "username"); >>> } >>> >>> public List<UserBean> getUsers() { >>> try { >>> List<UserBean> results = >>> usersDAO.getManagedUsers(stateBean.getUser().getUserId()); >>> if (results.size()) > 1) { >>> uOption = true; >>> } else { >>> uOption = false; >>> } >>> return results; >>> } catch (Exception ex) { >>> log.error("could not obtain users: " + ex.getMessage()); >>> } >>> return null; >>> } >>> >>> >>> Another dislike I have is with the ValueEncoder which has to invoke the >>> DAO again to obtain a matching user although these were already loaded up >>> when the model was created. It would be nice if the model cached the users >>> and simply referred back to them there. >>> >>> public UserBean toValue(String clientValue) { >>> try { >>> return usersDAO.getUser(Integer.parseInt(clientValue)); >>> } catch (Exception ex) { >>> log.error("user encoder could not resolve clientValue to a >>> UserBean: " >>> + ex.getMessage()); >>> return null; >>> } >>> } >>> >>> So overall I see the need for some shared cache with the select component, >>> just loading a map up should do it? >>> >>> John >>> ----- Original Message ----- >>> From: Geoff Callender >>> To: Tapestry users >>> Sent: Sunday, December 30, 2012 3:00 PM >>> Subject: Re: select blankOption >>> >>> >>> Some code please. >>> >>> On 31/12/2012, at 1:42 AM, John wrote: >>> >>>> I got that to work, it's great, I hadn't notice all the values can >>> have a prefix to change the scope. >>>> >>>> The problem is that the method that returns the option values and sets >>> the blankOption value is invoked after the blankOption getter. >>>> >>>> This is a problem I have hit before where a property value depends on >>> the result of a property value that is invoked later. I don't really want >>> to store results in the session and am wondering if I should use a cache >>> instead. >>>> >>>> Is there any recomended approach in Tapestry? Maybe I should use >>> ehCache? >>>> >>>> My typical example is a property that returns a collection from a DAO >>> to iterate over for a table or select list, and then some other property >>> whos state depends on that result in some way. So far I have been using >>> intermediate helper beans to bind the related state data. >>>> >>>> John >>>> ----- Original Message ----- >>>> From: Geoff Callender >>>> To: Tapestry users >>>> Sent: Sunday, December 30, 2012 1:37 PM >>>> Subject: Re: select blankOption >>>> >>>> >>>> Ah, so you were. Same applies. >>>> >>>> On 31/12/2012, at 12:24 AM, John wrote: >>>> >>>>> I was talking about blankOption, but I'll try with the prop prefix. >>>>> ----- Original Message ----- >>>>> From: Geoff Callender >>>>> To: Tapestry users >>>>> Sent: Sunday, December 30, 2012 12:16 PM >>>>> Subject: Re: select blankOption >>>>> >>>>> >>>>> The default prefix is "literal". Use "prop", eg. >>> blankLabel="prop:yourProperty". >>>>> >>>>> See Binding Expressions in >>> http://tapestry.apache.org/component-parameters.html . >>>>> >>>>> Cheers, >>>>> >>>>> Geoff >>>>> >>>>> On 30/12/2012, at 11:07 PM, John wrote: >>>>> >>>>>> I would like to choose dynamically whether to display the blank >>> option in my select component. >>>>>> >>>>>> I am using it to display an ALL value and don't want to show this if >>> the select has only 1 option. >>>>>> >>>>>> Unfortunately the docs say that the blankOption is a literal and not >>> a property. Is there any way to change that easily? >>>>>> >>>>>> Maybe it's easiest just to add a new option with the name and value >>> I want? >>>>>> >>>>>> John >>>>> >>>>> >>>>> --------------------------------------------------------------------- >>>>> To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org >>>>> For additional commands, e-mail: users-h...@tapestry.apache.org >>>> >>>> >>>> --------------------------------------------------------------------- >>>> To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org >>>> For additional commands, e-mail: users-h...@tapestry.apache.org >>> >>> >>> --------------------------------------------------------------------- >>> To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org >>> For additional commands, e-mail: users-h...@tapestry.apache.org >>> > --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org