An application developer can implement listeners as classes or as
managed bean methods. If a listener is a managed bean method, the page
author references the method from either the component’s
valueChangeListener
attribute or its actionListener
attribute. If
the listener is a class, the page author can reference the listener from
either an f:valueChangeListener
tag or an f:actionListener
tag and
nest the tag inside the component tag to register the listener on the
component.
This section explains how to register a NameChanged
value-change
listener and a BookChange
action listener implementation on
components. The Duke’s Bookstore case study includes both of these
listeners.
Registering a Value-Change Listener on a Component
A page author can register a ValueChangeListener
implementation on a
component that implements EditableValueHolder
by nesting an
f:valueChangeListener
tag within the component’s tag on the page. The
f:valueChangeListener
tag supports the attributes shown in
Table 11-5, one of which must be used.
Table 11-5 Attributes for the f:valueChangeListener Tag
Attribute |
Description |
type
|
References the fully qualified class name of a
ValueChangeListener implementation. Can accept a literal or a value
expression. |
binding
|
References an object that implements ValueChangeListener .
Can accept only a value expression, which must point to a managed bean
property that accepts and returns a ValueChangeListener
implementation. |
The following example shows a value-change listener registered on a
component:
<h:inputText id="name"
size="30"
value="#{cashierBean.name}"
required="true"
requiredMessage="#{bundle.ReqCustomerName}">
<f:valueChangeListener
type="javaeetutorial.dukesbookstore.listeners.NameChanged" />
</h:inputText>
In the example, the core tag type
attribute specifies the custom
NameChanged
listener as the ValueChangeListener
implementation
registered on the name
component.
After this component tag is processed and local values have been
validated, its corresponding component instance will queue the
ValueChangeEvent
associated with the specified ValueChangeListener
to the component.
Registering an Action Listener on a Component
A page author can register an ActionListener
implementation on a
command component by nesting an f:actionListener
tag within the
component’s tag on the page. Similarly to the f:valueChangeListener
tag, the f:actionListener
tag supports both the type
and binding
attributes. One of these attributes must be used to reference the action
listener.
Here is an example of an h:commandLink
tag that references an
ActionListener
implementation:
<h:commandLink id="Duke" action="bookstore">
<f:actionListener
type="javaeetutorial.dukesbookstore.listeners.LinkBookChangeListener" />
<h:outputText value="#{bundle.Book201}"/>
</h:commandLink>
The type
attribute of the f:actionListener
tag specifies the fully
qualified class name of the ActionListener
implementation. Similarly
to the f:valueChangeListener
tag, the f:actionListener
tag also
supports the binding
attribute. See
Binding Converters, Listeners, and
Validators to Managed Bean Properties for more information about
binding listeners to managed bean properties.
In addition to the actionListener
tag that allows you register a
custom listener onto a component, the core tag library includes the
f:setPropertyActionListener
tag. You use this tag to register a
special action listener onto the ActionSource
instance associated with
a component. When the component is activated, the listener will store
the object referenced by the tag’s value
attribute into the object
referenced by the tag’s target
attribute.
The bookcatalog.xhtml
page of the Duke’s Bookstore application uses
f:setPropertyActionListener
with two components: the h:commandLink
component used to link to the bookdetails.xhtml
page and the
h:commandButton
component used to add a book to the cart:
<h:dataTable id="books"
value="#{store.books}"
var="book"
headerClass="list-header"
styleClass="list-background"
rowClasses="list-row-even, list-row-odd"
border="1"
summary="#{bundle.BookCatalog}" >
...
<h:column>
<f:facet name="header">
<h:outputText value="#{bundle.ItemTitle}"/>
</f:facet>
<h:commandLink action="#{catalog.details}"
value="#{book.title}">
<f:setPropertyActionListener target="#{requestScope.book}"
value="#{book}"/>
</h:commandLink>
</h:column>
...
<h:column>
<f:facet name="header">
<h:outputText value="#{bundle.CartAdd}"/>
</f:facet>
<h:commandButton id="add"
action="#{catalog.add}"
value="#{bundle.CartAdd}">
<f:setPropertyActionListener target="#{requestScope.book}"
value="#{book}"/>
</h:commandButton>
</h:column>
The h:commandLink
and h:commandButton
tags are within an
h:dataTable
tag, which iterates over the list of books. The var
attribute refers to a single book in the list of books.
The object referenced by the var
attribute of an h:dataTable
tag is
in page scope. However, in this case you need to put this object into
request scope so that when the user activates the commandLink
component to go to bookdetails.xhtml
or activates the commandButton
component to go to bookcatalog.xhtml
, the book data is available to
those pages. Therefore, the f:setPropertyActionListener
tag is used to
set the current book object into request scope when the commandLink
or
commandButton
component is activated.
In the preceding example, the f:setPropertyActionListener
tag’s
value
attribute references the book
object. The
f:setPropertyActionListener
tag’s target
attribute references the
value expression requestScope.book
, which is where the book
object
referenced by the value
attribute is stored when the commandLink
or
the commandButton
component is activated.