dev@jsftemplating.java.net

Re: JSFTemplating: question relating to DropDown component

From: Anissa Lam <Anissa.Lam_at_Sun.COM>
Date: Sat, 07 Oct 2006 00:06:42 -0700

Hi Ken,
Thanks for the detailed explanation, as always. I took the easy way
out :-)
By setting some request attribute so that i know what state i am in, i
just navigate() back to the same page, which means it will need to
create the page again. In the beforeCreate event of the page, i set
the field back plus recreate the initial options of the DropDown.
This page only has 3 fields, so this is simple enough to recreate the
component tree. The page now behaves exactly what i want.

thanks
Anissa.

Ken Paulsen wrote:
>
> Hi Anissa,
>
> The problem is not that the dropDown doesn't honor the before
> encode... the "event" component inside it isn't allowed by the
> DropDown component.
>
> Also, depending on the component, encoding may begin before its
> children... so generally, you'll want to do the following instead:
>
> <sun:property label="ABC">
> <event>
> <!beforeEncode
> ...
> />
> <sun:dropDown ...>
> <!afterEncode
> />
> </event>
> </sun:property>
>
> The one issue you may run into here is that if you want to use
> relative information in this case (not that common), it will refer to
> the <event> which is the parent of the dropDown -- not the dropDown
> itself. Also, components that are implemented using JSFTemplating
> don't need the <event> component to invoke the beforeEncode /
> afterEncode events (the <event> component is one of these components
> which is how it works). <staticText> is another JSFTemplating component.
>
> I hope this helps!
>
> Your 2nd question was: How do I get the option lists to change between
> refreshes?
>
> Well... this is a little tricky. The way this component was written
> is plain wrong in my opinion. :) I tried to help this by making the
> factory hide some of the ugliness of the interface to this component.
> The component requires a List (or array, I think) of "Option"
> objects... the "Option" objects *must* be of that type (even they it
> extends SelectItem and could easily have been to allow SelectItem also
> -- but it casts to Option). The problem with this design is that
> Option (or even SelectItem) are not types that you're likely to have
> coming from your backend (database, mbean, etc.) :) So this component
> requires you to shuffle data, reference specific class files (I use
> reflection just to avoid the build dependency on this), and
> complicates how you work with the "data" which now is not just data --
> it includes component-specific classes.
>
> To hide this, I allow you to pass in data (List or array) and I make
> everything work. While this solves *most* of the problem... the
> component itself is still the same. If you want work with the
> existing data (add, remove, replace the options), you now have to work
> w/ Option List (or array).
>
> It would probably be a good idea to provide a handler to help with
> this (i.e. the handler can take the component and new list(s) as input
> and set it for you doing the correct conversions to the Option List).
> Other related handlers may also be useful.
>
> If we do this, this presents an interesting question: Where do these
> handlers belong? So far, we haven't answered where component-specific
> handlers should go (although I think we already have an
> OptionsHandlers.java file). I think it would be a good idea to think
> about this... I'm open to suggestions, including continuing to put
> them in the "handlers" package w/ a name like "OptionsHandlers.java".
> But, I think I would rather place them closer to the component
> factories to which they are related -- in fact, I think the factory
> class itself may be a good place. Since "apt" takes care of the
> mapping and provides a place for the framework and developers to find
> the handlers, I don't see a need to group them in a common package.
> The advantage of doing this also provides a way to separate out
> unwanted component libraries from those you want. I plan to
> eventually support building jsftemplating.jar with a sub-set of the
> supported components -- this would keep the size down, and would allow
> build dependencies w/o requiring everyone to satisfy them. What do
> you think?
>
> Lastly... you asked about deleting and recreating the component
> itself.... Well, this doesn't work like JATO. The parent component
> isn't aware of the children it's supposed to have. So if you delete
> one, it won't get recreated. You can create it yourself, there's a
> method called "createChild()" in
> com.sun.jsftemplating.component.ComponentUtil... you'll need to get
> the LayoutComponent ($this{layoutElement} will help... but if you're
> in the beforeEncode, you'll probably end up w/ the <event> and have to
> search for the <dropDown>). You'll want to make sure you replace the
> child (not just add / remove) b/c order matters in the list of
> children. So... I think this option is as much (if not more) work
> than replacing the data.
>
> If only the component were written to support this... then you'd be
> able to #{} bind to the data and it'd resolve it and convert it as
> needed... you wouldn't have to do anything. :( Unfortunately w/o
> rewriting the component I can't do much more. That is a thought... we
> could extend the component and override their getter's to resolve the
> #{} to the "options"/"values" properties we added. This would defer
> the evaluation and solve your problem... this might be the easiest
> way... to test this, we could just have the factory instantiate our
> extended class (no need to register it w/ the faces-config.xml). Let
> me think about that...
>
> Ken
>
> Ken
>
>
> Anissa Lam wrote:
>> Hi Ken,
>> Does the DropDown component honors the <!beforeEncode> event ?
>>
>> I have the following:
>>
>> <sun:property label="ABC" >
>> <event>
>> <!beforeEncode
>> println(value="!!!!!!!!!! beforeEncode of
>> Property -- This one shows up !!!" );
>> />
>> </event>
>> <sun:dropDown labels=${changeEveryRefresh}
>> selected="#{wizardPoolExtra.connectionDefinition}" required="#{true}" >
>> <event>
>> <!beforeEncode
>> println(value="!!!! beforeEncode of
>> DropDown, Never see this one !!" );
>> />
>> <!beforeCreate
>> println(value="!!!! beforeCreate of
>> DropDown, This one shows up !!! );
>> />
>> </event>
>> </sun:dropDown>
>> </sun:property>
>>
>> I need to change the dropdown list when the page redisplay. Is there
>> any way to force the UI component to be recreated so that i can make
>> use of the labels in the factory ? Otherwise, i have to write java
>> code to do the 'setItems' myself.
>>
>> thanks
>> Anissa.