Developing with Jakarta Faces Technology
This chapter provides an overview of managed beans and explains how to write methods and properties of managed beans that are used by a Jakarta Faces application. This chapter also introduces the Bean Validation feature.
Managed Beans in Jakarta Faces Technology
A typical Jakarta Faces application includes one or more managed beans, each of which can be associated with the components used in a particular page. This section introduces the basic concepts of creating, configuring, and using managed beans in an application.
Using Jakarta Faces Technology in Web Pages and Using Converters, Listeners, and Validators show how to add components to a page and connect them to server-side objects by using component tags and core tags. These chapters also show how to provide additional functionality to the components through converters, listeners, and validators. Developing a Jakarta Faces application also involves the task of programming the server-side objects: managed beans, converters, event handlers, and validators. |
Creating a Managed Bean
A managed bean is created with a constructor with no arguments, a set of properties, and a set of methods that perform functions for a component. Each of the managed bean properties can be bound to one of the following:
-
A component value
-
A component instance
-
A converter instance
-
A listener instance
-
A validator instance
The most common functions that managed bean methods perform include the following:
-
Validating a component’s data
-
Handling an event fired by a component
-
Performing processing to determine the next page to which the application must navigate
As with all JavaBeans components, a property consists of a private data field and a set of accessor methods, as shown by this code:
private Integer userNumber = null;
...
public void setUserNumber(Integer user_number) {
userNumber = user_number;
}
public Integer getUserNumber() {
return userNumber;
}
When bound to a component’s value, a bean property can be any of the basic primitive and numeric types or any Java object type for which the application has access to an appropriate converter.
For example, a property can be of type java.util.Date
if the application has access to a converter that can convert the Date
type to a String
and back again.
See Writing Bean Properties for information on which types are accepted by which component tags.
When a bean property is bound to a component instance, the property’s type must be the same as the component object.
For example, if a jakarta.faces.component.UISelectBoolean
component is bound to the property, the property must accept and return a UISelectBoolean
object.
Likewise, if the property is bound to a converter, validator, or listener instance, the property must be of the appropriate converter, validator, or listener type.
For more information on writing beans and their properties, see Writing Bean Properties.
Using the EL to Reference Managed Beans
To bind component values and objects to managed bean properties or to reference managed bean methods from component tags, page authors use the Expression Language syntax. As explained in Overview of the EL, the following are some of the features that the EL offers:
-
Deferred evaluation of expressions
-
The ability to use a value expression to both read and write data
-
Method expressions
Deferred evaluation of expressions is important because the Jakarta Faces lifecycle is split into several phases in which component event handling, data conversion and validation, and data propagation to external objects are all performed in an orderly fashion.
The implementation must be able to delay the evaluation of expressions until the proper phase of the lifecycle has been reached.
Therefore, the implementation’s tag attributes always use deferred-evaluation syntax, which is distinguished by the #{}
delimiter.
To store data in external objects, almost all Jakarta Faces tag attributes use lvalue expressions, which are expressions that allow both getting and setting data on external objects.
Finally, some component tag attributes accept method expressions that reference methods that handle component events or validate or convert component data.
To illustrate a Jakarta Faces tag using the EL, the following tag references a method that validates user input:
<h:inputText id="inputGuess"
value="#{userNumberBean.userNumber}"
required="true" size="3"
disabled="#{userNumberBean.number eq userNumberBean.userNumber ...}"
validator="#{userNumberBean.validateNumberRange}">
</h:inputText>
This tag binds the inputGuess
component’s value to the UserNumberBean.userNumber
managed bean property by using an lvalue expression.
The tag uses a method expression to refer to the UserNumberBean.validateNumberRange
method, which performs validation of the component’s local value.
The local value is whatever the user types into the field corresponding to this tag.
This method is invoked when the expression is evaluated.
Nearly all Jakarta Faces tag attributes accept value expressions. In addition to referencing bean properties, value expressions can reference lists, maps, arrays, implicit objects, and resource bundles.
Another use of value expressions is to bind a component instance to a managed bean property.
A page author does this by referencing the property from the binding
attribute:
<h:outputLabel for="fanClub"
rendered="false"
binding="#{cashierBean.specialOfferText}"
value="#{bundle.DukeFanClub}"/>
</h:outputLabel>
In addition to using expressions with the standard component tags, you can configure your custom component properties to accept expressions by creating jakarta.el.ValueExpression
or jakarta.el.MethodExpression
instances for them.
For information on the EL, see Expression Language.
For information on referencing managed bean methods from component tags, see Referencing a Managed Bean Method.
Writing Bean Properties
As explained in Managed Beans in Jakarta Faces Technology, a managed bean property can be bound to one of the following items:
-
A component value
-
A component instance
-
A converter implementation
-
A listener implementation
-
A validator implementation
These properties follow the conventions of JavaBeans components (also called beans). For more information on JavaBeans components, see the JavaBeans Tutorial at https://docs.oracle.com/javase/tutorial/javabeans/index.html.
The component’s tag binds the component’s value to a managed bean property by using its value
attribute and binds the component’s instance to a managed bean property by using its binding
attribute.
Likewise, all the converter, listener, and validator tags use their binding
attributes to bind their associated implementations to managed bean properties.
See Binding Component Values and Instances to Managed Bean Properties and Binding Converters, Listeners, and Validators to Managed Bean Properties for more information.
To bind a component’s value to a managed bean property, the type of the property must match the type of the component’s value to which it is bound.
For example, if a managed bean property is bound to a UISelectBoolean
component’s value, the property should accept and return a boolean
value or a Boolean
wrapper Object
instance.
To bind a component instance to a managed bean property, the property must match the type of component.
For example, if a managed bean property is bound to a UISelectBoolean
instance, the property should accept and return a UISelectBoolean
value.
Similarly, to bind a converter, listener, or validator implementation to a managed bean property, the property must accept and return the same type of converter, listener, or validator object.
For example, if you are using the convertDateTime
tag to bind a jakarta.faces.convert.DateTimeConverter
to a property, that property must accept and return a DateTimeConverter
instance.
The rest of this section explains how to write properties that can be bound to component values, to component instances for the component objects described in Adding Components to a Page Using HTML Tag Library Tags, and to converter, listener, and validator implementations.
Writing Properties Bound to Component Values
To write a managed bean property that is bound to a component’s value, you must match the property type to the component’s value.
Acceptable Types of Component Values lists the jakarta.faces.component
classes and the acceptable types of their values.
Component Class | Acceptable Types of Component Values |
---|---|
|
Any of the basic primitive and numeric types or any Java programming language object type for which an appropriate |
|
|
|
|
|
|
|
|
When they bind components to properties by using the value
attributes of the component tags, page authors need to ensure that the corresponding properties match the types of the components' values.
UIInput and UIOutput Properties
The UIInput
and UIOutput
component classes are represented by the component tags that begin with h:input
and h:output
, respectively (for example, h:inputText
and h:outputText
).
In the following example, an h:inputText
tag binds the name
component to the name
property of a managed bean called CashierBean
.
<h:inputText id="name"
size="30"
value="#{cashierBean.name}"
...>
</h:inputText>
The following code snippet from the managed bean CashierBean
shows the bean property type bound by the preceding component tag:
protected String name = null;
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
As described in Using the Standard Converters, to convert the value of an input or output component you can either apply a converter or create the bean property bound to the component with the matching type. Here is the example tag, from Using DateTimeConverter, that displays the date on which items will be shipped.
<h:outputText value="#{cashierBean.shipDate}">
<f:convertDateTime type="date" dateStyle="full" />
</h:outputText>
The bean property represented by this tag must have a type of java.util.Date
.
The following code snippet shows the shipDate
property, from the managed bean CashierBean
, that is bound by the tag’s value in the preceding example:
private Date shipDate;
public Date getShipDate() {
return this.shipDate;
}
public void setShipDate(Date shipDate) {
this.shipDate = shipDate;
}
UIData Properties
The UIData
component class is represented by the h:dataTable
component tag.
UIData
components must be bound to one of the managed bean property types listed in Acceptable Types of Component Values.
Data components are discussed in Using Data-Bound Table Components.
Here is part of the start tag of dataTable
from that section:
<h:dataTable id="items"
...
value="#{cart.items}"
...
var="item">
The value expression points to the items
property of a shopping cart bean named cart
.
The cart
bean maintains a map of ShoppingCartItem
beans.
The getItems
method from the cart
bean populates a List
with ShoppingCartItem
instances that are saved in the items
map when the customer adds books to the cart, as shown in the following code segment:
public synchronized List<ShoppingCartItem> getItems() {
List<ShoppingCartItem> results = new ArrayList<ShoppingCartItem>();
results.addAll(this.items.values());
return results;
}
All the components contained in the UIData
component are bound to the properties of the cart
bean that is bound to the entire UIData
component.
For example, here is the h:outputText
tag that displays the book title in the table:
<h:commandLink action="#{showcart.details}">
<h:outputText value="#{item.item.title}"/>
</h:commandLink>
The title is actually a link to the bookdetails.xhtml
page.
The h:outputText
tag uses the value expression #{item.item.title}
to bind its UIOutput
component to the title
property of the Book
entity.
The first item in the expression is the ShoppingCartItem
instance that the h:dataTable
tag is referencing while rendering the current row.
The second item in expression refers to the item
property of ShoppingCartItem
, which returns an Object
(in this case, a Book
).
The title
part of the expression refers to the title
property of Book
.
The value of the UIOutput
component corresponding to this tag is bound to the title
property of the Book
entity:
private String title;
...
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
The UIData component (and UIRepeat) supports the Map
and Iterable
interfaces, as well as custom types.
For UIData and UIRepeat, the supported types are:
-
null
(becomes empty list) -
jakarta.faces.model.DataMode
-
java.util.List
-
java.lang.Object
[] -
java.sql.ResultSet
-
jakarta.servlet.jsp.jstl.sql.Result
-
java.util.Collection
-
java.lang.Iterable
-
java.util.Map
-
java.lang.Object
(becomes ScalarDataModel)
UISelectBoolean Properties
The UISelectBoolean
component class is represented by the component tag h:selectBooleanCheckbox
.
Managed bean properties that hold a UISelectBoolean
component’s data must be of boolean
or Boolean
type.
The example selectBooleanCheckbox
tag from the section Displaying Components for Selecting One Value binds a component to a property.
The following example shows a tag that binds a component value to a boolean
property:
<h:selectBooleanCheckbox title="#{bundle.receiveEmails}"
value="#{custFormBean.receiveEmails}">
</h:selectBooleanCheckbox>
<h:outputText value="#{bundle.receiveEmails}">
Here is an example property that can be bound to the component represented by the example tag:
private boolean receiveEmails = false;
...
public void setReceiveEmails(boolean receiveEmails) {
this.receiveEmails = receiveEmails;
}
public boolean getReceiveEmails() {
return receiveEmails;
}
UISelectMany Properties
The UISelectMany
component class is represented by the component tags that begin with h:selectMany
(for example, h:selectManyCheckbox
and h:selectManyListbox
).
Because a UISelectMany
component allows a user to select one or more items from a list of items, this component must map to a bean property of type List
or array
.
This bean property represents the set of currently selected items from the list of available items.
The following example of the selectManyCheckbox
tag comes from Displaying Components for Selecting Multiple Values:
<h:selectManyCheckbox id="newslettercheckbox"
layout="pageDirection"
value="#{cashierBean.newsletters}">
<f:selectItems value="#{cashierBean.newsletterItems}"/>
</h:selectManyCheckbox>
Here is the bean property that maps to the value
of the selectManyCheckbox
tag from the preceding example:
private String[] newsletters;
public void setNewsletters(String[] newsletters) {
this.newsletters = newsletters;
}
public String[] getNewsletters() {
return this.newsletters;
}
The UISelectItem
and UISelectItems
components are used to represent all the values in a UISelectMany
component.
See UISelectItems Properties for information on writing the bean properties for the UISelectItem
and UISelectItems
components.
UISelectOne Properties
The UISelectOne
component class is represented by the component tags that begin with h:selectOne
(for example, h:selectOneRadio
and h:selectOneListbox
).
UISelectOne
properties accept the same types as UIInput
and UIOutput
properties, because a UISelectOne
component represents the single selected item from a set of items.
This item can be any of the primitive types and anything else for which you can apply a converter.
Here is an example of the h:selectOneMenu
tag from Displaying a Menu Using the h:selectOneMenu Tag:
<h:selectOneMenu id="shippingOption"
required="true"
value="#{cashierBean.shippingOption}">
<f:selectItem itemValue="2"
itemLabel="#{bundle.QuickShip}"/>
<f:selectItem itemValue="5"
itemLabel="#{bundle.NormalShip}"/>
<f:selectItem itemValue="7"
itemLabel="#{bundle.SaverShip}"/>
</h:selectOneMenu>
Here is the bean property corresponding to this tag:
private String shippingOption = "2";
public void setShippingOption(String shippingOption) {
this.shippingOption = shippingOption;
}
public String getShippingOption() {
return this.shippingOption;
}
Note that shippingOption
represents the currently selected item from the list of items in the UISelectOne
component.
The UISelectItem
and UISelectItems
components are used to represent all the values in a UISelectOne
component.
This is explained in Displaying a Menu Using the h:selectOneMenu Tag.
For information on how to write the managed bean properties for the UISelectItem
and UISelectItems
components, see UISelectItems Properties.
UISelectItem Properties
A UISelectItem
component represents a single value in a set of values in a UISelectMany
or a UISelectOne
component.
A UISelectItem
component must be bound to a managed bean property of type jakarta.faces.model.SelectItem
.
A SelectItem
object is composed of an Object
representing the value along with two Strings
representing the label and the description of the UISelectItem
object.
The example selectOneMenu
tag from UISelectOne Properties contains selectItem
tags that set the values of the list of items in the page.
Here is an example of a bean property that can set the values for this list in the bean:
SelectItem itemOne = null;
SelectItem getItemOne(){
return itemOne;
}
void setItemOne(SelectItem item) {
itemOne = item;
}
UISelectItems Properties
UISelectItems
components are children of UISelectMany
and UISelectOne
components.
Each UISelectItems
component is composed of a set of either UISelectItem
instances or any collection of objects, such as an array, a list, or even POJOs.
The following code snippet from CashierBean
shows how to write the properties for selectItems
tags containing SelectItem
instances.
private String[] newsletters;
private static final SelectItem[] newsletterItems = {
new SelectItem("Duke's Quarterly"),
new SelectItem("Innovator's Almanac"),
new SelectItem("Duke's Diet and Exercise Journal"),
new SelectItem("Random Ramblings")
};
...
public void setNewsletters(String[] newsletters) {
this.newsletters = newsletters;
}
public String[] getNewsletters() {
return this.newsletters;
}
public SelectItem[] getNewsletterItems() {
return newsletterItems;
}
Here, the newsletters
property represents the SelectItems
object, whereas the newsletterItems
property represents a static array of SelectItem
objects.
The SelectItem
class has several constructors; in this example, the first argument is an Object
representing the value of the item, whereas the second argument is a String
representing the label that appears in the UISelectMany
component on the page.
Writing Properties Bound to Component Instances
A property bound to a component instance returns and accepts a component instance rather than a component value. The following components bind a component instance to a managed bean property:
<h:selectBooleanCheckbox id="fanClub"
rendered="false"
binding="#{cashierBean.specialOffer}" />
<h:outputLabel for="fanClub"
rendered="false"
binding="#{cashierBean.specialOfferText}"
value="#{bundle.DukeFanClub}" />
</h:outputLabel>
The selectBooleanCheckbox
tag renders a check box and binds the fanClub
UISelectBoolean
component to the specialOffer
property of CashierBean
.
The outputLabel
tag binds the value of the value
attribute, which represents the check box’s label, to the specialOfferText
property of CashierBean
.
If the user orders more than $100 worth of books and clicks the Submit button, the submit
method of CashierBean
sets both components' rendered
properties to true
, causing the check box and label to display when the page is re-rendered.
Because the components corresponding to the example tags are bound to the managed bean properties, these properties must match the components' types.
This means that the specialOfferText
property must be of type UIOutput
, and the specialOffer
property must be of type UISelectBoolean
:
UIOutput specialOfferText = null;
UISelectBoolean specialOffer = null;
public UIOutput getSpecialOfferText() {
return this.specialOfferText;
}
public void setSpecialOfferText(UIOutput specialOfferText) {
this.specialOfferText = specialOfferText;
}
public UISelectBoolean getSpecialOffer() {
return this.specialOffer;
}
public void setSpecialOffer(UISelectBoolean specialOffer) {
this.specialOffer = specialOffer;
}
For more general information on component binding, see Managed Beans in Jakarta Faces Technology.
For information on how to reference a managed bean method that performs navigation when a button is clicked, see Referencing a Method That Performs Navigation.
For more information on writing managed bean methods that handle navigation, see Writing a Method to Handle Navigation.
Writing Properties Bound to Converters, Listeners, or Validators
All the standard converter, listener, and validator tags included with Jakarta Faces technology support binding attributes that allow you to bind converter, listener, or validator implementations to managed bean properties.
The following example shows a standard convertDateTime
tag using a value expression with its binding
attribute to bind the jakarta.faces.convert.DateTimeConverter
instance to the convertDate
property of LoginBean
:
<h:inputText value="#{loginBean.birthDate}">
<f:convertDateTime binding="#{loginBean.convertDate}" />
</h:inputText>
The convertDate
property must therefore accept and return a DateTimeConverter
object, as shown here:
private DateTimeConverter convertDate;
public DateTimeConverter getConvertDate() {
...
return convertDate;
}
public void setConvertDate(DateTimeConverter convertDate) {
convertDate.setPattern("EEEEEEEE, MMM dd, yyyy");
this.convertDate = convertDate;
}
Because the converter is bound to a managed bean property, the managed bean property can modify the attributes of the converter or add new functionality to it.
In the case of the preceding example, the property sets the date pattern that the converter uses to parse the user’s input into a Date
object.
The managed bean properties that are bound to validator or listener implementations are written in the same way and have the same general purpose.
Writing Managed Bean Methods
Methods of a managed bean can perform several application-specific functions for components on the page. These functions include
-
Performing processing associated with navigation
-
Handling action events
-
Performing validation on the component’s value
-
Handling value-change events
Why Use Managed Beans
By using a managed bean to perform these functions, you eliminate the need to implement the jakarta.faces.validator.Validator
interface to handle the validation or one of the listener interfaces to handle events.
Also, by using a managed bean instead of a Validator
implementation to perform validation, you eliminate the need to create a custom tag for the Validator
implementation.
In general, it is good practice to include these methods in the same managed bean that defines the properties for the components referencing these methods. The reason for doing so is that the methods might need to access the component’s data to determine how to handle the event or to perform the validation associated with the component.
The following sections explain how to write various types of managed bean methods.
Writing a Method to Handle Navigation
An action method, a managed bean method that handles navigation processing, must be a public method that takes no parameters and returns an Object
, which is the logical outcome that the navigation system uses to determine the page to display next.
This method is referenced using the component tag’s action
attribute.
The following action method is from the managed bean CashierBean
, which is invoked when a user clicks the Submit button on the page.
If the user has ordered more than $100 worth of books, this method sets the rendered
properties of the fanClub
and specialOffer
components to true
, causing them to be displayed on the page the next time that page is rendered.
After setting the components' rendered
properties to true
, this method returns the logical outcome null
.
This causes the Jakarta Faces implementation to re-render the page without creating a new view of the page, retaining the customer’s input.
If this method were to return purchase
, which is the logical outcome to use to advance to a payment page, the page would re-render without retaining the customer’s input.
In this case, you want to re-render the page without clearing the data.
If the user does not purchase more than $100 worth of books or if the thankYou
component has already been rendered, the method returns bookreceipt
.
The Jakarta Faces implementation loads the bookreceipt.xhtml
page after this method returns:
public String submit() {
...
if ((cart().getTotal() > 100.00) && !specialOffer.isRendered()) {
specialOfferText.setRendered(true);
specialOffer.setRendered(true);
return null;
} else if (specialOffer.isRendered() && !thankYou.isRendered()) {
thankYou.setRendered(true);
return null;
} else {
...
cart.clear();
return ("bookreceipt");
}
}
Typically, an action method will return a String
outcome, as shown in the preceding example.
Alternatively, you can define an Enum
class that encapsulates all possible outcome strings and then make an action method return an enum
constant, which represents a particular String
outcome defined by the Enum
class.
The following example uses an Enum
class to encapsulate all logical outcomes:
public enum Navigation {
main, accountHist, accountList, atm, atmAck, transferFunds,
transferAck, error
}
When it returns an outcome, an action method uses the dot notation to reference the outcome from the Enum
class:
public Object submit(){
...
return Navigation.accountHist;
}
The section Referencing a Method That Performs Navigation explains how a component tag references this method. The section Writing Properties Bound to Component Instances explains how to write the bean properties to which the components are bound.
Writing a Method to Handle an Action Event
A managed bean method that handles an action event must be a public method that accepts an action event and returns void
.
This method is referenced using the component tag’s actionListener
attribute.
Only components that implement jakarta.faces.component.ActionSource
can refer to this method.
In the following example, a method from a managed bean named ActionBean
processes the event of a user clicking one of the links on the page:
public void chooseBookFromLink(ActionEvent event) {
String current = event.getComponent().getId();
FacesContext context = FacesContext.getCurrentInstance();
String bookId = books.get(current);
context.getExternalContext().getSessionMap().put("bookId", bookId);
}
This method gets the component that generated the event from the event object; then it gets the component’s ID, which is a code for the book.
The method matches the code against a HashMap
object that contains the book codes and corresponding book ID values.
Finally, the method sets the book ID by using the selected value from the HashMap
object.
Referencing a Method That Handles an Action Event explains how a component tag references this method.
Writing a Method to Perform Validation
Instead of implementing the jakarta.faces.validator.Validator
interface to perform validation for a component, you can include a method in a managed bean to take care of validating input for the component.
A managed bean method that performs validation must accept a jakarta.faces.context.FacesContext
, the component whose data must be validated, and the data to be validated, just as the validate
method of the Validator
interface does.
A component refers to the managed bean method by using its validator
attribute.
Only values of UIInput
components or values of components that extend UIInput
can be validated.
Here is an example of a managed bean method that validates user input, from The guessnumber-cdi CDI Example:
public void validateNumberRange(FacesContext context,
UIComponent toValidate,
Object value) {
if (remainingGuesses <= 0) {
((UIInput) toValidate).setValid(false);
FacesMessage message = new FacesMessage("No guesses left!");
context.addMessage(toValidate.getClientId(context), message);
return;
}
int input = (Integer) value;
if (input < minimum || input> maximum) {
((UIInput) toValidate).setValid(false);
FacesMessage message = new FacesMessage("Invalid guess");
context.addMessage(toValidate.getClientId(context), message);
}
}
The validateNumberRange
method performs two different validations.
-
If the user has run out of guesses, the method sets the
valid
property of theUIInput
component tofalse
. Then it queues a message onto theFacesContext
instance, associating the message with the component ID, and returns. -
If the user has some remaining guesses, the method then retrieves the local value of the component. If the input value is outside the allowable range, the method again sets the
valid
property of theUIInput
component tofalse
, queues a different message on theFacesContext
instance, and returns.
See Referencing a Method That Performs Validation for information on how a component tag references this method.
Writing a Method to Handle a Value-Change Event
A managed bean that handles a value-change event must use a public method that accepts a value-change event and returns void
.
This method is referenced using the component’s valueChangeListener
attribute.
This section explains how to write a managed bean method to replace the jakarta.faces.event.ValueChangeListener
implementation.
The following example tag comes from Registering a Value-Change Listener on a Component, where the h:inputText
tag with the id
of name
has a ValueChangeListener
instance registered on it.
This ValueChangeListener
instance handles the event of entering a value in the field corresponding to the component.
When the user enters a value, a value-change event is generated, and the processValueChange(ValueChangeEvent)
method of the ValueChangeListener
class is invoked:
<h:inputText id="name"
size="30"
value="#{cashierBean.name}"
required="true"
requiredMessage="#{bundle.ReqCustomerName}">
<f:valueChangeListener
type="ee.jakarta.tutorial.dukesbookstore.listeners.NameChanged" />
</h:inputText>
Instead of implementing ValueChangeListener
, you can write a managed bean method to handle this event.
To do this, you move the processValueChange(ValueChangeEvent)
method from the ValueChangeListener
class, called NameChanged
, to your managed bean.
Here is the managed bean method that processes the event of entering a value in the name
field on the page:
public void processValueChange(ValueChangeEvent event)
throws AbortProcessingException {
if (null != event.getNewValue()) {
FacesContext.getCurrentInstance().getExternalContext().
getSessionMap().put("name", event.getNewValue());
}
}
To make this method handle the ValueChangeEvent
generated by an input component, reference this method from the component tag’s valueChangeListener
attribute.
See Referencing a Method That Handles a Value-Change Event for more information.