And you can probably still do the JSR-303 validation server-side in processSubmission() with something like this (untested)...
import javax.inject.Inject; import javax.validation.ConstraintViolation; import javax.validation.Validator; import javax.validation.groups.Default; @Inject private Validator validator; Set<ConstraintViolation<AddressBean>> errors = validator.validate(aBean, Default.class); for (ConstraintViolation<AddressBean> error : errors) { if (error.getPropertyPath().equals("streetName")) { form.recordError(streetNameField, error.getMessage()); } else if (error.getPropertyPath().equals("city")) { form.recordError(cityField, error.getMessage()); } // etc... } On 02/11/2013, at 10:18 PM, Geoff Callender wrote: > Sorry, just realised you want the Address component to handle an address > bean, not the parent form's bean. Hmmm. That probably means JSR-303 > annotations in the address bean will be ignored, but you can still do manual > validation like that shown in processSubmission(). > > On 02/11/2013, at 10:10 PM, Geoff Callender wrote: > >> Assuming you're editing a bean, try this. In parent put something like >> this... >> >> <t:form t:id="form" t:validate="myBean"> >> <t:if test="myBean"> >> <t:errors /> >> >> <div> >> <t:label for="firstname"/> >> <input t:id="firstname" value="myBean.firstName" >> t:type="textfield"/> >> </div> >> >> <t:myform.address mybean="myBean"/> >> >> <div> >> <input value="message:save-label" t:type="submit"/> >> <input t:id="cancel" value="message:cancel-label" >> t:type="submit" t:mode="cancel"/> >> </div> >> </t:if> >> <t:if test="!myBean"> >> My bean ${myBeanId} does not exist.<br/><br/> >> </t:if> >> </form> >> >> ...and in Address component, stuff like... >> >> <t:content> >> <div> >> <t:label for="streetname"/> >> <input t:id="streetname" value="aBean.streetName" >> t:type="textfield"/> >> </div> >> <div> >> <t:label for="countryname"/> >> <input t:id="countryname" value="countryName" >> t:type="textfield"/> >> </div> >> </t:content> >> >> If you're using JSR-303 Bean Validation, be sure the value uses exactly the >> same case for the bean's property name as the bean uses, eg. "streetName", >> not "streetname". Otherwise, the bean validator will miss it. >> >> If there's stuff you need to set up before rendering, then put it >> setupRender(). >> >> If there's stuff you need to set up before rendering AND on submit, then put >> it in a ComponentAction and, in setupRender(), ask FormSupport to >> storeAndExecute() it. See >> http://jumpstart.doublenegative.com.au/jumpstart/examples/component/subformasafield1 >> for a use case and code. >> >> If there's stuff you need to do on submit, then put it in a ComponentAction >> and, in afterRender(), ask FormSupport to store() it. >> >> : >> import org.apache.tapestry5.ValidationTracker; >> import org.apache.tapestry5.annotations.Component; >> import org.apache.tapestry5.annotations.Environmental; >> import org.apache.tapestry5.annotations.Parameter; >> import org.apache.tapestry5.annotations.Property; >> import org.apache.tapestry5.corelib.components.TextField; >> import org.apache.tapestry5.services.FormSupport; >> : >> public class Address { >> >> // The context >> >> @Parameter(required = true, allowNull = false) >> @Property >> private MyBean aBean; >> >> // Screen fields >> >> @Property >> private String countryName; >> >> // Generally useful bits and pieces. >> >> @Component(id = "countryName") >> private TextField countryNameField; >> >> @Environmental >> private FormSupport formSupport; >> >> @Environmental >> private ValidationTracker tracker; >> >> private static final ProcessSubmission PROCESS_SUBMISSION = new >> ProcessSubmission(); >> >> // The code >> >> final void setupRender() { >> >> // In here, set up for render, eg. convert myBean.countryCode >> to a countryName... >> >> } >> >> void afterRender() { >> >> // If we are inside a form, ask FormSupport to store >> PROCESS_SUBMISSION in its list of actions to do on submit. >> // If I contain other components, their actions will already be >> in the list, before PROCESS_SUBMISSION. That is >> // because this method, afterRender(), is late in the sequence. >> This guarantees PROCESS_SUBMISSION will be >> // executed on submit AFTER the components I contain are >> processed (which includes their validation). >> >> if (formSupport != null) { >> formSupport.store(this, PROCESS_SUBMISSION); >> } >> >> } >> >> private static class ProcessSubmission implements >> ComponentAction<MyBean> { >> private static final long serialVersionUID = 1L; >> >> public void execute(MyBean component) { >> component.processSubmission(); >> } >> >> // This is optional... >> @Override >> public String toString() { >> return this.getClass().getSimpleName() + >> ".ProcessSubmission"; >> } >> }; >> >> private void processSubmission() { >> >> // Translate derived values. Eg. convert countryName to a >> countryCode... >> >> // Validate. >> >> if (countryCode == null) { >> tracker.recordError(countryNameField, >> getMessages().get("country-required")); >> return; >> } >> >> // Modify the bean with derived values. >> >> myBean.setCountryCode(countryCode); >> >> } >> >> } >> >> Cheers, >> >> Geoff >> >> On 01/11/2013, at 3:14 AM, Hottois Ludwig wrote: >> >>> Hi everyone ! >>> >>> I was asking myself during a long time how to correctly create a form for >>> create a user, but in this form, i want include a part wich is a form for >>> create an address. >>> >>> I was thinking first about putting this part of the form, which is created >>> for instruct informations about the user address, into a component, and >>> include this into the parent tml like : >>> >>> <t :form> >>> <t :texfield value= <name >/> >>> >>> <t :myform.address/> >>> .... >>> >>> </form> >>> >>> And into myform.address put : >>> >>> <t :container ...> >>> <t :textfield value= < roadName >/> >>> .... >>> </t :container> >>> >>> But if i do this, when i click on the submit on the principal form, the >>> fired event of validation asking is not catched by the < myform.address > >>> component i think ? >>> >>> And when i click on my submit, my principal form doesn't have any >>> information about my differents fields into the sub form. >>> >>> What are the best practices? >>> >>> Thanks, >>> Ludwig >>> >>> ________________________________ >>> >>> Ce message et les pi?ces jointes sont confidentiels et r?serv?s ? l'usage >>> exclusif de ses destinataires. Il peut ?galement ?tre prot?g? par le secret >>> professionnel. Si vous recevez ce message par erreur, merci d'en avertir >>> imm?diatement l'exp?diteur et de le d?truire. L'int?grit? du message ne >>> pouvant ?tre assur?e sur Internet, la responsabilit? de Worldline ne pourra >>> ?tre recherch?e quant au contenu de ce message. Bien que les meilleurs >>> efforts soient faits pour maintenir cette transmission exempte de tout >>> virus, l'exp?diteur ne donne aucune garantie ? cet ?gard et sa >>> responsabilit? ne saurait ?tre recherch?e pour tout dommage r?sultant d'un >>> virus transmis. >>> >>> This e-mail and the documents attached are confidential and intended solely >>> for the addressee; it may also be privileged. If you receive this e-mail in >>> error, please notify the sender immediately and destroy it. As its >>> integrity cannot be secured on the Internet, the Worldline liability cannot >>> be triggered for the message content. Although the sender endeavours to >>> maintain a computer virus-free network, the sender does not warrant that >>> this transmission is virus-free and will not be liable for any damages >>> resulting from any virus transmitted. >> >