The Definitive Guide to JSF in Java EE 8: Building Web Applications with JavaServer Faces by Arjan Tijms & Bauke Scholtz

The Definitive Guide to JSF in Java EE 8: Building Web Applications with JavaServer Faces by Arjan Tijms & Bauke Scholtz

Author:Arjan Tijms & Bauke Scholtz [Arjan Tijms]
Language: eng
Format: epub
Publisher: Apress
Published: 2018-05-28T21:00:00+00:00


Composite Components

Sometimes, you would like to have a group of related input components to represent a single model value. A classic example is having three <h:selectOneMenu> drop-downs representing day, month, and year which are ultimately bound to a single java.time.LocalDate property in the backing bean. This is not trivial to implement with just an include file or a tag file. You would need some additional Java-based logic which makes sure that, e.g., the day drop-down doesn’t show the values 29, 30, or 31 depending on the currently selected month, and that it converts the submitted values to a full-fledged LocalDate instance, and vice versa. But you can’t and shouldn’t put any Java code in any Facelet.

You’ll perhaps think of just creating a dedicated backing bean for this case. But this is not sufficient either. It doesn’t allow you to cleanly hook on the component’s life cycle through the JSF phases: collecting the individual submitted values from multiple components, converting them into a single LocalDate instance, if necessary throwing a converter exception during the validations phase, and letting the JSF life cycle automatically skip the remaining phases. A backing bean’s setter method or action method is far from the right place for that logic. It would be invoked too late anyway. And, it would feel strange to be able to reference and potentially manipulate the very same backing bean via an EL expression on an arbitrary place in the Facelet.

This is exactly where composite components come into the picture: composing a bunch of existing JSF components into virtually a single component tied to a single model value and ultimately using it exactly the same way as you would be using a plain <h:inputText>. Imagine a <t:inputLocalTime> composite component composed of two <h:selectOneMenu> components tied to a single java.time.LocalTime model value. Instead of a backing bean, you can use a full-fledged UIComponent instance as a so-called backing component.

First create a dedicated subfolder in main/webapp/resources folder (and thus not main/java/resources!), for example, main/webapp/resources/components. There you can put Facelets files representing composite components. The subfolder is then to be used in the XML namespace URI after http://xmlns.jcp.org/jsf/composite as shown next.

xmlns:t="http://xmlns.jcp.org/jsf/composite/components"

Note that the XML namespace prefix of “t” clashes with one which we already defined before for tag files. This is of course not the intent. You may choose a different XML namespace for composite components. It’s, however, also possible to let them share the same custom XML namespace URI http://example.com.tags . This can be achieved by adding a <composite-library-name> to the *.taglib.xml which in turn must represent the name of the dedicated subfolder.

<composite-library-name>components</composite-library-name>

This way all composite components are also available by the same XML namespace as tag files.

<... xmlns:t="http://example.com/tags">

...

<t:inputLocalTime ... />

The file name of the Facelets file representing the composite component will become the tag name. So, in order to have a <t:inputLocalTime>, we need an inputLocalTime.xhtml file in the main/webapp/resources/components folder. Following is a kickoff example of what it can look like:

<ui:component

xmlns:="http://www.w3.org/1999/xhtml"

xmlns:f="http://xmlns.jcp.org/jsf/core"

xmlns:h="http://xmlns.jcp.org/jsf/html"

xmlns:ui="http://xmlns.jcp.org/jsf/facelets"

xmlns:cc="http://xmlns.jcp.org/jsf/composite"

>

<cc:interface componentType="inputLocalTime">

<cc:attribute name="value" type="java.time.LocalTime"

shortDescription="Selected time. Defaults to 00:00.">

</cc:attribute>

<cc:attribute name="required" type="boolean"

shortDescription="Required state. Defaults to false.



Download



Copyright Disclaimer:
This site does not store any files on its server. We only index and link to content provided by other sites. Please contact the content providers to delete copyright contents if any and email us, we'll remove relevant links or contents immediately.