https://issues.apache.org/jira/browse/TAP5-1512
On Mon, Apr 25, 2011 at 12:15 PM, Adam Zimowski <zimowsk...@gmail.com> wrote: > After more debugging, the problem seems to be with Tapestry's > IdAllocator and how it generates client side id's for select > components, particularly when Zone is updated. > > In this case, what happens is that every time I update zone while form > is in error, the ID of my select changes with incremented suffix: > > ORIGINAL AS EXPECTED BY FORM: a_state > > After resetting country causing state dropdown to repopulate, id > becomes: a_state_1 > then a_state_2 etc... > > This causes ValidationTracker put error under wrong key, and > consequently error to field binding in tracker's map cannot be > resolved, causing <t:error/> thinking that all is good. That's why > <t:errors/> does display the error, as it simply loops over collection > of errors. > > Out of lack of deep understanding of Tapestry, I coded a simple hack > to verify that if select update via zone kept its original id things > would work, and indeed, the following hack fixes the problem for my > case: > > Tapestry 5.2.5, AbstractField line 183: > > private void setupControlName(String controlName) > { > if(controlName.startsWith("a_state")) > this.controlName = "a_state"; > else > this.controlName = controlName; > } > > I tried filing this in JIRA but it seems to be down (Bad Gateway). In > any case, I do not know enough about framework internals to fix this > properly. Additional insight would be highly appreciated. > > Adam > > On Thu, Apr 21, 2011 at 11:33 AM, Adam Zimowski <zimowsk...@gmail.com> wrote: >> Okay, now I am pretty sure this is a bug related to usage of >> <t:error/> in 5.2.5. If I put <t:errors/> (which I didn't have >> before), the state required error shows up as expected. If I use >> <t:error/> attached to state field, the error does not show. >> >> It's like looking for a needle in a haystack.. lol..... still could >> appreciate suggestion if anyone knows how to temporarily fix this. >> >> Adam >> >> On Thu, Apr 21, 2011 at 11:14 AM, Adam Zimowski <zimowsk...@gmail.com> wrote: >>> Quick update: >>> >>> By debugging Select component I see that validation tracker correctly >>> records the error when I submit the blank option for state. The blank >>> option is submitted throug the following use case: >>> >>> 1. Select country and state (both have blank options therefore are >>> required), but leave other fields empty. >>> 2. Submit form. Validation on required fields (such as city, zip) >>> results in form rendering error messages. Note: Country and State are >>> not in error at this point. >>> 3. While correcting errors on the form, change country. As a result, >>> state select component is repopulated (zone update), and default blank >>> option is select. Do not chose state. >>> 4. Submit form with state NOT selected. Debugging select shows that it >>> records error. Yet form is not displaying the error. >>> >>> So the problem is that on the first submit Tapestry is not rendering >>> the error, which is really there. Bug? >>> >>> Adam >>> >>> >>> >>> On Thu, Apr 21, 2011 at 10:20 AM, Adam Zimowski <zimowsk...@gmail.com> >>> wrote: >>>> I'm sorry, I am on Tapestry 5.2.5 :-) >>>> >>>> On Thu, Apr 21, 2011 at 10:19 AM, Adam Zimowski <zimowsk...@gmail.com> >>>> wrote: >>>>> @Josh - When I debug Select in 5.2.4 (break on processSubmission(), >>>>> line 166), selectedValue is blank which is expected. So select >>>>> correctly submits without a value, it's just it seems that the >>>>> validator does not recognize that select state was repopulated via >>>>> zone and consequently no value was submitted the 2nd time. It seems to >>>>> me like the form validator somehow things that select has the value >>>>> from the prior submission, but it really doesn't since it was reset >>>>> via zone update. >>>>> >>>>> @Mark - by validation kicks in, I meant that form was submitted and >>>>> validated. I have a debug on state code passed from the state select >>>>> component when form activates, and AddressUiBean comes back with the >>>>> correct value. That is, when I select the state from the dropdown, >>>>> AddressUiBean carries the state as expected. Even when form is in >>>>> error, as I change the country thereby causing state dropdown get >>>>> repopulated, and resubmit the form with blank option for state (did >>>>> not select the state), AddressUiBean shows null state code (as >>>>> expected). Yet the form does not report the error on the required >>>>> state field. >>>>> >>>>> Adam >>>>> >>>>> On Wed, Apr 20, 2011 at 10:25 PM, Mark <mark-li...@xeric.net> wrote: >>>>>> When you say "Validation kicks in" does this occur after a submit? If >>>>>> so, >>>>>> is it possible that AddressUIBean is remembering the value that was >>>>>> present >>>>>> when the submit occurred and then on the second submit it is getting set >>>>>> to >>>>>> null again? >>>>>> >>>>>> At the point when you would expect an error to occur, what is the value >>>>>> of >>>>>> the state field? That should give you a good clue as to what is >>>>>> happening. >>>>>> >>>>>> Mark >>>>>> >>>>>> On Tue, Apr 19, 2011 at 5:11 PM, Adam Zimowski <zimowsk...@gmail.com> >>>>>> wrote: >>>>>> >>>>>>> I have a typical address form with street, city zip textfields and two >>>>>>> dropdowns: country and state. The state dropdown is wrapped in a zone >>>>>>> so that when country is selected, states are populated: >>>>>>> >>>>>>> <div class="kk-field" t:type="zone" t:id="stateModelZone"><t:select >>>>>>> t:id="a_state" model="stateModel" validate="required" >>>>>>> value="stateKode" blankOption="ALWAYS" blankLabel="literal:--Please >>>>>>> Select"/></div> >>>>>>> >>>>>>> All works okay, except for a test case my business analyst found which >>>>>>> I can't figure out. >>>>>>> >>>>>>> You fill out a form, pick a country then pick a state and suppose you >>>>>>> leave city field empty which is required. Validation kicks in. While >>>>>>> correcting a city error, you decide to switch a country causing state >>>>>>> list to get repopulated and state be not selected again. Suppose you >>>>>>> submit the form, I expect the error that state is required, but error >>>>>>> is not thrown. Only if I resubmit the form a second time, state will >>>>>>> be flagged in error. >>>>>>> >>>>>>> I am resetting state to null on country change. I have even tried >>>>>>> setting form state field in error, none of which works. >>>>>>> >>>>>>> ---------- TML -------------- >>>>>>> >>>>>>> <t:form t:id="registrationForm"> >>>>>>> <div class="kk-hdr">Address Information</div> >>>>>>> <div class="kk-row"> >>>>>>> <div class="kk-label"><t:label for="a_line1"/> :</div> >>>>>>> <div class="kk-field"><t:textfield t:id="a_line1" >>>>>>> value="address.line1"/></div> >>>>>>> <t:error class="literal:kk-error" for="a_line1"/> >>>>>>> </div> >>>>>>> <div class="kk-row"> >>>>>>> <div class="kk-label"><t:label for="a_line2"/> :</div> >>>>>>> <div class="kk-field"><t:textfield t:id="a_line2" >>>>>>> value="address.line2"/></div> >>>>>>> <t:error class="literal:kk-error" for="a_line2"/> >>>>>>> </div> >>>>>>> <div class="kk-row"> >>>>>>> <div class="kk-label"><t:label for="a_line3"/> :</div> >>>>>>> <div class="kk-field"><t:textfield t:id="a_line3" >>>>>>> value="address.line3"/></div> >>>>>>> <t:error class="literal:kk-error" for="a_line3"/> >>>>>>> </div> >>>>>>> <div class="kk-row"> >>>>>>> <div class="kk-label"><t:label for="a_city"/> :</div> >>>>>>> <div class="kk-field"><t:textfield t:id="a_city" >>>>>>> value="address.city"/></div> >>>>>>> <t:error class="literal:kk-error" for="a_city"/> >>>>>>> </div> >>>>>>> <div class="kk-row"> >>>>>>> <div class="kk-label"><t:label for="a_zip"/> :</div> >>>>>>> <div class="kk-field"><t:textfield t:id="a_zip" >>>>>>> value="address.zipCode"/></div> >>>>>>> <t:error class="literal:kk-error" for="a_zip"/> >>>>>>> </div> >>>>>>> <div class="kk-row"> >>>>>>> <div class="kk-label"><t:label for="a_state"/> :</div> >>>>>>> <div class="kk-field" t:type="zone" t:id="stateModelZone"><t:select >>>>>>> t:id="a_state" model="stateModel" validate="required" >>>>>>> value="address.stateCode" blankOption="ALWAYS" >>>>>>> blankLabel="literal:--Please Select"/></div> >>>>>>> <t:error class="literal:kk-error" for="a_state"/> >>>>>>> </div> >>>>>>> <div class="kk-row"> >>>>>>> <div class="kk-label"><t:label for="a_country"/> :</div> >>>>>>> <div class="kk-field"><t:select t:id="a_country" model="countryModel" >>>>>>> value="address.countryCode" blankOption="NEVER" >>>>>>> zone="stateModelZone"/></div> >>>>>>> </div> >>>>>>> <p> >>>>>>> <input t:type="submit" value="message:submit-label"/> >>>>>>> </p> >>>>>>> </t:form> >>>>>>> >>>>>>> ---------------- Page class ------------------------- >>>>>>> >>>>>>> public class Register extends BasePage { >>>>>>> >>>>>>> @Inject >>>>>>> private Logger log; >>>>>>> >>>>>>> @Inject >>>>>>> private UtilityServiceRemote utilityService; >>>>>>> >>>>>>> @Persist >>>>>>> @Property >>>>>>> private AddressUiBean address; >>>>>>> >>>>>>> @OnEvent(value=EventConstants.PREPARE) >>>>>>> void initialize() { >>>>>>> if(address == null) address = new AddressUiBean(); >>>>>>> if(contact == null) contact = new ContactUiBean(); >>>>>>> if(registration == null) registration = new >>>>>>> RegisterUiBean(); >>>>>>> >>>>>>> String countryCode = address.getCountryCode(); >>>>>>> if(countryCode == null) { >>>>>>> Locale locale = getLocale(); >>>>>>> countryCode = locale.getCountry(); >>>>>>> address.setCountryCode(countryCode); >>>>>>> } >>>>>>> >>>>>>> log.debug("address state code {}", >>>>>>> address.getStateCode()); >>>>>>> } >>>>>>> >>>>>>> @Cached >>>>>>> public Map<String, String> getCountryModel() { >>>>>>> Map<String, String> model = new LinkedHashMap<String, >>>>>>> String>(); >>>>>>> List<CountryBean> countries = >>>>>>> utilityService.getAllCountries(getLocale()); >>>>>>> for(CountryBean country : countries) { >>>>>>> String code = country.getCodeIsoAlpha2(); >>>>>>> String description = country.getShortName(); >>>>>>> log.debug("code: {}, description: {}", code, >>>>>>> description); >>>>>>> model.put(code, description); >>>>>>> } >>>>>>> return model; >>>>>>> } >>>>>>> >>>>>>> @OnEvent(value=EventConstants.VALUE_CHANGED, >>>>>>> component="a_country") >>>>>>> public Object onCountrySelected(String aCountryCode) { >>>>>>> log.debug("selected country: {}", aCountryCode); >>>>>>> address.setStateCode(null); >>>>>>> return stateModelZone.getBody(); >>>>>>> } >>>>>>> >>>>>>> @Cached >>>>>>> public Map<String, String> getStateModel() { >>>>>>> Map<String, String> model = new LinkedHashMap<String, >>>>>>> String>(); >>>>>>> String countryCode = address.getCountryCode(); >>>>>>> List<StateProvinceBean> states = >>>>>>> >>>>>>> utilityService.getAllStateProvincesForCountry(countryCode, >>>>>>> getLocale()); >>>>>>> for(StateProvinceBean state : states) { >>>>>>> String code = state.getLookupCode(); >>>>>>> String name = state.getLongName(); >>>>>>> log.debug("code: {}, name {}", code, name); >>>>>>> model.put(code, name); >>>>>>> } >>>>>>> return model; >>>>>>> } >>>>>>> } >>>>>>> >>>>>>> Adam >>>>>>> >>>>>>> --------------------------------------------------------------------- >>>>>>> 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