In this recipe, we will develop a spinner composite component. The special thing in this recipe is that you will see how to add JavaScript code for controlling a composite component. The appearance of the component can be seen in the following screenshot:
We have developed this recipe with NetBeans 6.8, JSF 2.0, and GlassFish v3. The JSF 2.0 classes were obtained from the NetBeans JSF 2.0 bundled library.
By now, you should already be familiar with the mechanism of creating a composite component in JSF 2.0; therefore, we will skip the details regarding this aspect. To start with, the page itself is very simple:
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:e="http://java.sun.com/jsf/composite/spinner"> <h:head> <title> Creating a composite component with zero Java code </title> </h:head> <h:body> <e:spinner value="10" step="10"> </e:spinner> </h:body> </html>
As you see, the component name is spinner
, so the component page will be spinner.xhtml
. Let's see it and then discuss it:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:composite="http://java.sun.com/jsf/composite"> <h:head> <title>Creating a spinner composite component</title> </h:head> <h:body> <composite:interface> <composite:attribute name="value" required="true" /> <composite:attribute name="step" required="false" /> </composite:interface> <composite:implementation> <script type="text/javascript"> function goDirection(s) { var step = Number("#{cc.attrs.step}"); if ((isNaN(step)) || (step == 0)) { step = 1; } var obj = document.getElementById ("#{cc.clientId}"+":"+"nrID"); obj.value = Number(obj.value) + (s * step); return false; } </script> <h:inputText id="nrID" value="#{cc.attrs.value}"/> <h:commandButton id="leftID" value="-10" onclick="return goDirection(-1);"/> <h:commandButton id="rightID" value="+10" onclick="return goDirection(1);"/> </composite:implementation> </h:body> </html>
The big surprise lies in the <composite:implementation>
tag. Based on the JavaScript onClick
event, we fire events from two buttons—one button increases the spinner value by 10, while the other one decreases it. When a button is clicked, the mouse event onClick
is fired, and the getDirection
JavaScript function is called. Notice how we can use the #{…}
expression to gain access to component attributes. The #{cc.attrs.step}
expression is used to obtain the value of the step
attribute, while the #{cc.clientId}
expression returns the auto-generated component ID (if you want to control this ID value, then add an id
attribute to the spinner
tag). This ID is then concatenated with ":" and nrID
to form the complete ID.