tags:

views:

50

answers:

2

In the following scenario, the "hasA" condition is checked twice, is there a way to mimic this much similar to a if/else block so that the condition is evaluated only once

            <s:decorate template="/layout/display.xhtml">
                <h:outputText value="Print A." rendered="#{hasA}"/>
                <h:outputText value="Print B." rendered="#{!hasA}"/>
            </s:decorate>
+4  A: 

You can write the condition in value attribute with EL expression

 <h:outputText value="#{hasA ? 'Print A.' : 'Print B.'}" />
Odelya
This will result in one or the other of these controls being added to the JSF component tree. If a form were submitted and the view restored, it wouldn't matter what value `${hasA}` has, the tree has already been constructed and the original state is what will be re-rendered. Mixing JSF and non-JSF controls, immediate-evaluation and deferred evaluation expressions - this often results in surprising behaviour. I'm just pointing this out so that anyone using this snippet doesn't get a nasty shock.
McDowell
@McDowell - do you refer to my first solution with h:output text of to the solution with JSTL?
Odelya
He refers to the second one. The first one works...
Fortega
this is why I wrote the recommended approach - with rendered. However, I added a reference to the first comment
Odelya
@Odelya - I was referring to the mixture of JSTL and JSF tags
McDowell
Your outputtext example was perfect as an answer. Throwing JSTL through for no reason makes the answer clumsy. The OP didn't mention about JSTL at all and it's not the recommended way at any way. I also don't mention in every JSF+JSP answer that it can be done with *scriptlets* but that it's not recommended. If you cleanup the answer, you'll get a vote :)
BalusC
@BalusC - i am waiting:)
Odelya
See, there. To the OP: it's called the conditional operator. You'll probably know it from normal Java code as well. You can find an overview of all EL operators and expression examples [here](http://download.oracle.com/javaee/5/tutorial/doc/bnahq.html#bnaik).
BalusC
+1  A: 

To circumvent the problem, you can make sure the getter does not do any complicated stuff twice or basically returns a boolean. You should also make sure the getter is indempotent: calling it twice should yield the same result. To do so, you can either

  1. Compute lazily the boolean value and store it in a temporary field so that the second time the pre-computed value is returned.
  2. Change the logic so that the action that would result in a change of the boolean does actually update the boolean field, and the getter/setter is really just a getter/setter and does not compute anything.

The explanation is not crystal clear, but you should see the idea. I don't see anything wrong with having a simple getter evaluated multiple time.

ewernli
He prefers an elegant way to use it,meaning, not writing the same condition twice
Odelya
@Odelya Oh well, elegance is a matter of taste. I would advice to stick to simple `rendered` attribute, and not mix JSTL or write complex EL expression.
ewernli
as you said, a matter of taste..
Odelya
3. Use the Seam @Factory annotation to store the computed value in the context.
Damo