This lab enhances the trivia quiz from the previous lab as described
next.
Following the description are suggestions on how to proceed and more
about conditional rendering.
- Look at first.xhtml, rest.xhtml,
and done.xhtml, and identify the groups of components that
either always appear together or do not appear together
- These will be the content of h:panelGroups, all of
which can included in one page, say quiz.xhtml
- Their appearance will be controlled by their rendered attributes
- Identify the conditions under which
the h:panelGroups appear
- Create QuizBean properties to be used by
the rendered attributes of the h:panelGroups
- These will be readable boolean valued properties
that signal the conditions identified in step 2
- QuizBean must make sure these properties
are updated as the quiz proceeds
- Recall that boolean property getters start with
"is", not "get"
- Replace first.xhtml, rest.xhtml,
and done.xhtml with quiz.xhtml that uses
conditionally rendered h:panelGroups
- Test the web app — it should behave exactly
as before (i.e. it has been refactored)
- Implement and separately test selection
components:
- h:selectOneListbox in index.xhtml
— Note that only one command button needed, and its action
method startQuiz is not called with a parameter
- h:selectOneRadio in quiz.xhtml
- Implement and test CSS styles
- Computer science professors are often poor page stylists
— see if you can do better
In this section we describe conditional rendering in more detail and
how it relates to bean properties.
The
h:panelGroup tag and any other JSF HTML tag can use the
rendered
attribute like this:
<h:panelGroup rendered="condition-expression">
...
</h:panelGroup>
where
condition-expression evaluates to boolean. An example is:
<h:panelGroup rendered="true">
...
</h:panelGroup>
which means that the group of components in the body of the element will
always be rendered. That is not very useful, so instead use a
value
expression:
<h:panelGroup rendered="#{value-expression}">
...
</h:panelGroup>
where
value-expression is written in the JSF expression language as described
at the end of chapter 2.
Suppose you want to conditionally render the congratulatory message when
the user finishes a quiz, along with the button that takes the user back to
the opening page.
Then you need a way, in
value-expression, of testing
for the condition of the quiz being done. You probably already have
most of what you need:
- You already know the most common form of the value expression
syntax: bean.property.
- You must already have some way of checking for the quiz being
done in your QuizBean class, or you would not have been able to
return the "done" outcome.
You now have to be able to do a similar test in
the panel group's
value-expression.
However, that expression only has access
to bean properties and some basic operators as described on p. 69.
If you didn't have bean properties for that purpose before, you will
have to add them.
Suppose you have a
currentQuestion property as well as a
totalQuestions property, both integers, and suppose that
currentQuestion
starts at 1 and increments as questions are answered.
Then the
value-expression to render the group could be:
<h:panelGroup rendered="#{quizBean.currentQuestion == quizBean.totalQuestions}">
...
</h:panelGroup>
However, this is messy and starts exposing too much of the "business logic"
in the web page.
A better way would be to have one property, say
quizDone,
of type boolean, and to make sure that it is set to false when (and only
when) the quiz is done. Then you would use:
<h:panelGroup rendered="#{quizBean.quizDone}">
...
</h:panelGroup>