dev@jsftemplating.java.net

Re: JSFTemplating: question relating to DropDown component

From: Ken Paulsen <Ken.Paulsen_at_Sun.COM>
Date: Fri, 06 Oct 2006 21:10:01 -0700

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.