Some time ago I’ve posted an example to demonstrate how easy it is to create composite components with Facelets and JSF. The example is using scriptaculous slider widget and wraps it as a jsf component. In JSF 2.0 creating composite components is much easier thanks to the JSF 2.0 EZComp.
So here is the JSF 2.0 version of the slider component;
Page that has a slider;
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:barca="http://java.sun.com/jsf/composite/barca">
<h:head>
<title>Slider Demo</title>
</h:head>
<h:body>
<h:form>
<barca:inputSlider id="sld1" value="#{demo.number}" min="0" max="100"></barca:inputSlider>
</h:form>
</h:body>
</html>
And inputSlider.xhtml
<!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">
<body>
<composite:interface>
<composite:attribute name="id" required="true" />
<composite:attribute name="value" required="true" />
<composite:attribute name="min" required="false" />
<composite:attribute name="max" required="false"/>
</composite:interface>
<composite:implementation>
<h:outputScript name="protototype.js" library="scriptaculous" target="head"/>
<h:outputScript name="scriptaculous.js" library="scriptaculous" target="head"/>
<h:outputScript name="effects.js" library="scriptaculous" target="head"/>
<h:outputScript name="controls.js" library="scriptaculous" target="head"/>
<h:outputScript name="slider.js" library="scriptaculous" target="head"/>
<h:inputText id="sliderField" style="width:100px" value="#{compositeComponent.attrs.value}"></h:inputText>
<div id="#{compositeComponent.clientId}_track" style="width:105px;background-color:#aaa;height:5px;">
<div id="#{compositeComponent.clientId}_handle" style="width:5px;height:10px;background-color:#f00;cursor:move;"></div>
</div>
<script type="text/javascript">
var slider_#{compositeComponent.attrs.id} = new Control.Slider('#{compositeComponent.clientId}_handle','#{compositeComponent.clientId}_track',{range:$R(#{compositeComponent.attrs.min},#{compositeComponent.attrs.max})});
slider_#{compositeComponent.attrs.id}.options.onSlide = function(value){
$('#{compositeComponent.clientId}:sliderField').value = (value + '').split(".")[0];
};
</script>
</composite:implementation>
</body>
</html>
The output would be sth like;
You may ask so where do we write the xml to configure taglibs or any other thing. The answer is you don’t need any xml or annotation, the inputSlider.xhtml is enough! It is convention over configuration, if you put inputSlider.xml under your %WEBAPP%/resources/barca/inputSlider.xhtml you can add it the component taglib to your pages with xmlns:barca=”http://java.sun.com/jsf/composite/barca”. Also another cool thing is that assume you want to bundle your component library in a jar and distribute/reuse it in several applications. This time place your inputSlider.xhtml and other composite components in %YOUR_JAR%/META-INF/resources/barca/inputSlider.xhtml.
Compared to my facelets version of slider this one is much scalable, in JSF 2.0 inputSlider is not a tag that is added to the component tree, it is an actual component so that I can take the advantage of compositeComponent.clientId attribute to use multiple instances of slider in one page. In facelets version of slider I had to use tomahawk forceId. Also using the new h:outputScript library I can avoid including the same resource more than once if there are multiple sliders in the page. In summary EZComp keeps it’s promise and as you see really simplifies JSF component development.