On Tue, Nov 25, 2014 at 11:33 PM, mscoon <msc...@gmail.com> wrote: > I don't want to use an IComponentOnBeforeRenderListener as it is an > application wide facility whereas what I'm doing applies to a couple of > pages only. > > But you suggestion gave me an idea. I am now using a behavior which I add > to all form components in ListView#populateItem(). The behavior marks the > components as invalid in onConfigure() which comes before onBeforeRender() > and hence before the IComponentOnBeforeRenderListener. > > The problem with this solution is that this code is much more complicated > than what I was doing originally. Now I have to put the validation errors > in a transient field which is set in the form's onConfigure() method, and > use this field to retrieve the errors from within Behavior#onConfigure(). > What I tried to do originally was much cleaner, the model object was > validated and the components invalidated from within a single method. > >
> It does seem like AbstractRepeater should have a postOnPopulate() method to > allow client code to access the created components before onBeforeRender() > is executed, don't you think? > You can use populateItem() for this, no ? > > On Tue, Nov 25, 2014 at 4:29 PM, Martin Grigorov <mgrigo...@apache.org> > wrote: > > > OK, but isn't it possible to mark the form components as invalid with > > IComponentOnBeforeRenderListener too ? > > Just add the new IComponentOnBeforeRenderListener in the collection > before > > FormErrorDecorator. > > > > Martin Grigorov > > Wicket Training and Consulting > > https://twitter.com/mtgrigorov > > > > On Tue, Nov 25, 2014 at 4:15 PM, mscoon <msc...@gmail.com> wrote: > > > > > attachValidationErrors has nothing to do with FormErrorDecorator. It is > > > just some code that adds validation errors to some form components. > > > > > > I use it because I want to show validation errors right when then form > > > opens, and not after a submit. For instance if the user loads a record > > for > > > editing, and this record has some wrong data in it, I want to > immediately > > > show the validation errors when the page renders and not have to wait > > until > > > a submit. > > > > > > On Tue, Nov 25, 2014 at 11:50 AM, Martin Grigorov < > mgrigo...@apache.org> > > > wrote: > > > > > > > Hi, > > > > > > > > On Mon, Nov 24, 2014 at 10:34 PM, mscoon <msc...@gmail.com> wrote: > > > > > > > > > Martin, > > > > > > > > > > I'll try once again to explain my problem and if it's still unclear > > > I'll > > > > > make the quickstart. > > > > > > > > > > What you say is right, the sequence of events is as you said. > > > > > > > > > > My problem is that everything happens in > > > > AbstractRepeater#onBeforeRender(). > > > > > So I have to put my code "attachValidationErrors" either before or > > > after > > > > > AbstractRepeater#onBeforeRender(). > > > > > > > > > > If I put it before, the form components have not yet been created > > > > > (onPopulate() has not yet been called). > > > > > > > > > > If I put it after, the componentPostOnBeforeRenderListeners have > > > already > > > > > run so the ErrorDecorator thinks there are no errors. > > > > > > > > > > What I need is a way for my code to run *after* onPopulate() but > > > *before* > > > > > onBeforeRenderChildren(). There is no such hook though. > > > > > > > > > > Let me also expand my pseudocode a bit in case this helps: > > > > > > > > > > class MyPage extends WebPage { > > > > > > > > > > pyblic MyPage() { > > > > > > > > > > > > > > > > > > > Form form = new Form("form", model) { > > > > > override onBeforeRender() { > > > > > attachValidationErrors(); > > > > > > > > > > > > > Why do you need to call that here at all ? Why you want to traverse > the > > > > sub-tree manually ? > > > > > > > > By using IComponentOnBeforeRenderListener you are being notified for > > each > > > > and every Component in the component tree. > > > > So your listener should just check whether the component is an > instance > > > of > > > > FormComponent and if its name matches (and the other complex logic > you > > > > have) then report the error. > > > > > > > > > > > > > onBeforeRender(); > > > > > } > > > > > }; > > > > > add(form); > > > > > > > > > > ListView list = new ListView("list", model2) { > > > > > public populateItem(ListItem listItem) { > > > > > add(new TextField("name", new PropertyModel(model2, > > > "name"))); > > > > > } > > > > > } > > > > > form.add(list); > > > > > > > > > > } > > > > > > > > > > void attachValidationErrors() { > > > > > form.visitChildren(FormComponent.class, new > > > > > IVisitor<FormComponent,Void>() { > > > > > void component(FormComponent<?> obj, IVisit<Void> visit) > { > > > > > if (obj.getId().equals("name") /* and some other > > complex > > > > > logic here */) { > > > > > obj.error("Please provide a name"); > > > > > } > > > > > } > > > > > }); > > > > > } > > > > > > > > > > I think this makes my problem quite evident. I can't find the right > > > place > > > > > to put the call to attachValidationErrors(). > > > > > > > > > > Or perhaps I need a different implements for FormErrorDecorator. > > > > > > > > > > > > > > > > > > > > On Mon, Nov 24, 2014 at 5:13 PM, Martin Grigorov < > > mgrigo...@apache.org > > > > > > > > > wrote: > > > > > > > > > > > Hi, > > > > > > > > > > > > Maybe I miss something from your description but I think > ListView's > > > > items > > > > > > should have their #onBeforeRender() method called as any other > > > > component > > > > > in > > > > > > the tree. > > > > > > > > > > > > > org.apache.wicket.markup.repeater.AbstractRepeater#onBeforeRender() > > > > first > > > > > > calls #onPopulate() (where ListView adds its children) and then > > calls > > > > > > super.onBeforeRender() > > > > > > where org.apache.wicket.MarkupContainer#onBeforeRenderChildren() > > that > > > > > calls > > > > > > #onBeforeRender() for all children components. So > > > > > > IComponentOnBeforeRenderListener should be notified. > > > > > > > > > > > > Maybe a quickstart will make it easier for understanding where is > > the > > > > > > problem. > > > > > > > > > > > > > > > > > > On Mon, Nov 24, 2014 at 4:52 PM, mscoon <msc...@gmail.com> > wrote: > > > > > > > > > > > > > Martin, > > > > > > > > > > > > > > Application#getComponentPostOnBeforeRenderListeners is how I am > > > > already > > > > > > > registering my FormErrorDecorator. > > > > > > > > > > > > > > Attaching the validation errors after super.onBeforeRender() > does > > > not > > > > > > work > > > > > > > even for components that are statically added and not part of a > > > list > > > > > > view. > > > > > > > > > > > > > > Here's some psuedocode: > > > > > > > > > > > > > > Form form = new Form("form", model) { > > > > > > > protected void onBeforeRender() { > > > > > > > super.onBeforeRender(); > > > > > > > attachValidationErrors(); > > > > > > > } > > > > > > > } > > > > > > > > > > > > > > super.onBeforeRender() calls onBeforeRender() on all children > > which > > > > in > > > > > > turn > > > > > > > calls both the componentPreOnBeforeRenderListeners and the > > > > > > > componentPostOnBeforeRenderListeners. So by the time > > > > > > > attachValidationErrors() is called the error decorator has run > > and > > > > > > finished > > > > > > > (and done nothing as it found no errors). > > > > > > > > > > > > > > If I move attachValidationErrors before super.onBeforeRender(), > > > then > > > > it > > > > > > > works for statically added form components. It does not work > for > > > > > > components > > > > > > > within ListViews because populateItem has not yet been called. > > > > > > > > > > > > > > I could move some of the error attaching logic within > > populateItem > > > > but > > > > > > this > > > > > > > is ugly and leads to code duplication (as populateItem will not > > > > always > > > > > be > > > > > > > called because I need setReuseItems(true)). > > > > > > > > > > > > > > Any other ideas? > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > On Mon, Nov 24, 2014 at 3:23 PM, Martin Grigorov < > > > > mgrigo...@apache.org > > > > > > > > > > > > > wrote: > > > > > > > > > > > > > > > Hi, > > > > > > > > > > > > > > > > Try with org.apache.wicket.Application#getComponent*Post* > > > > > > > > OnBeforeRenderListeners() > > > > > > > > > > > > > > > > Martin Grigorov > > > > > > > > Wicket Training and Consulting > > > > > > > > https://twitter.com/mtgrigorov > > > > > > > > > > > > > > > > On Mon, Nov 24, 2014 at 2:50 PM, mscoon <msc...@gmail.com> > > > wrote: > > > > > > > > > > > > > > > > > Hi all, > > > > > > > > > > > > > > > > > > I am using a FormErrorDecorator that implements an > > > > > > > > > IComponentOnBeforeRenderListener in order to automatically > > > > attach a > > > > > > css > > > > > > > > > class to form components with validation errors (see > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > https://cwiki.apache.org/confluence/display/WICKET/Automatic+styling+of+form+errors > > > > > > > > > ). > > > > > > > > > > > > > > > > > > Sometimes I want to manually add errors to form components > > and > > > I > > > > > was > > > > > > > > doing > > > > > > > > > that in onBeforeRender() before the call to > > > > > super.onBeforeRender(). I > > > > > > > do > > > > > > > > > this because sometimes the object being edited is in an > > invalid > > > > > state > > > > > > > > and I > > > > > > > > > want to show the validation errors right when the form > opens > > > and > > > > > not > > > > > > > > after > > > > > > > > > a submit. This is working fine for most cases as the errors > > are > > > > > > > attached > > > > > > > > to > > > > > > > > > the form components before the FormErrorDecorator runs. > > > > > > > > > > > > > > > > > > However, form components inside a list view are not created > > > until > > > > > the > > > > > > > end > > > > > > > > > of ListView.onBeforeRender(). This means that I cannot > attach > > > > > errors > > > > > > > > before > > > > > > > > > this step because the list view items don't yet exist, and > > if I > > > > > > attach > > > > > > > > them > > > > > > > > > after onBeforeRender they are not picked up by the > > > > > > FormErrorDecorator. > > > > > > > > > > > > > > > > > > Any ideas? > > > > > > > > > > > > > > > > > > Thanks, > > > > > > > > > Marios > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >