Facelets: Templating
Pick your poison. Currently Facelets offers 3 different ways to modularize and decorate your pages/components.
Preface
Facelets is founded on the idea of compositions. This means that a UIComponent tree can be defined in multiple Facelet pages and executed in part or whole. Some other frameworks, like Tapestry, may define a single component within a page, Facelets instead marks the root of a branch of child components-- a composition if you will.
This means you can have an easily viewable HTML document (body/css/js) and all, but only use a portion of the page to define the reusable composition.
Templates
Compositions have a single attribute, "template", that can be used the same way that Struts Tiles does. Lets modify the composition example above for templates:
Now for the template--
When the Facelet is 'applied' and the tree is built, the template will be weaved in, using the default text/components if the definitions aren't passed. This functionality is the foundation of Facelet templating and has proven to be quite fast.
Includes
This is probably the most familiar method of modularizing content. This allows you to include another Facelet into the UIComponent tree.
The navigation that the include is pointing at could be an XML document with namespaces, or an XHTML page with namespaces that uses the 'ui:composition' tag as described above with templates.
Includes can also have child 'ui:param' tags that work the same as they do with JSP with a name and value attribute. These name/value pairs will be bound and passed to the included Facelet when the UIComponent tree is built:
Decorators
I previously wrote about 'templates' with compositions. Decorators behave exactly the same way, except that you are inlining the template into the page:
This has practical uses where it doesn't make sense to abstract out a composition into a separate document, but would still like to take advantage of templating.
Tag Files
Tag files are no different than any other page. This means that your tag file can be as simple as something like this:
You can note that I'm using the same param's that were defined in the 'include' example to prove a point. The include with params has the same behavior defining a tag:
You will get some performance gain by defining tags instead of using an include because the attributes are wired at compile time, where an include must fetch its child params on each execution.
At this point, you have to wonder how you go about specifying or binding files to tags. Tags must be defined in a Facelet tag library, such as:
As a side note, tag libraries can either be placed in the META-INF directory of your jar (same as a faces-config.xml), or specified in your application's web.xml.
That's it for now, more to come soon!
- Tag Files
- Decorators
- Includes
Preface
Facelets is founded on the idea of compositions. This means that a UIComponent tree can be defined in multiple Facelet pages and executed in part or whole. Some other frameworks, like Tapestry, may define a single component within a page, Facelets instead marks the root of a branch of child components-- a composition if you will.
Text before will be removed.
<ui:composition>
#{dynamic.text}
<h:inputText id="myText" value="#{foo.bar}"/>
</ui:composition>
Text after will be removed.
This means you can have an easily viewable HTML document (body/css/js) and all, but only use a portion of the page to define the reusable composition.
Templates
Compositions have a single attribute, "template", that can be used the same way that Struts Tiles does. Lets modify the composition example above for templates:
Text before will be removed.
<ui:composition template="/templates/menu.xhtml">
<ui:define name="title">
#{dynamic.text}
</ui:define>
<ui:define name="body">
<h:inputText id="myText" value="#{foo.bar}"/>
</ui:define>
</ui:composition>
Text after will be removed.
Now for the template--
Template Text before will be removed.
<ui:composition>
This Text will show up
<ui:insert name="title">
Default Title Text
</ui:insert>
This Text will also show up
<ui:insert name="body">
Default Body Text
</ui:insert>
So will this text
</ui:composition>
Template Text after will be removed.
When the Facelet is 'applied' and the tree is built, the template will be weaved in, using the default text/components if the definitions aren't passed. This functionality is the foundation of Facelet templating and has proven to be quite fast.
Includes
This is probably the most familiar method of modularizing content. This allows you to include another Facelet into the UIComponent tree.
<span id="leftNav">
<ui:include src="/WEB-INF/siteNav.xhtml"/>
</span>
The navigation that the include is pointing at could be an XML document with namespaces, or an XHTML page with namespaces that uses the 'ui:composition' tag as described above with templates.
Includes can also have child 'ui:param' tags that work the same as they do with JSP with a name and value attribute. These name/value pairs will be bound and passed to the included Facelet when the UIComponent tree is built:
<span id="leftNav">
<ui:include src="/WEB-INF/siteNav.xhtml">
<ui:param name="user" value="#{currentUser}"/>
<ui:param name="page" value="home"/>
</ui:include>
</span>
Decorators
I previously wrote about 'templates' with compositions. Decorators behave exactly the same way, except that you are inlining the template into the page:
Text before will show up
<ui:decorate template="/templates/menu.xhtml">
<ui:define name="title">
#{dynamic.text}
</ui:define>
<ui:define name="body">
<h:inputText id="myText" value="#{foo.bar}"/>
</ui:define>
</ui:decorate>
Text after will show up
This has practical uses where it doesn't make sense to abstract out a composition into a separate document, but would still like to take advantage of templating.
Tag Files
Tag files are no different than any other page. This means that your tag file can be as simple as something like this:
<!-- this is the whole file! -->
<composition xmlns="http://java.sun.com/jsf/facelet">
#{user.login} on page #{page}
</composition>
You can note that I'm using the same param's that were defined in the 'include' example to prove a point. The include with params has the same behavior defining a tag:
<my:echo user="#{currentUser}" page="home"/>
You will get some performance gain by defining tags instead of using an include because the attributes are wired at compile time, where an include must fetch its child params on each execution.
At this point, you have to wonder how you go about specifying or binding files to tags. Tags must be defined in a Facelet tag library, such as:
<facelet-taglib>
<namespace>http://www.mycompany.com/jsf</namespace>
<tag>
<tag-name>echo</tag-name>
<source>tags/echo.xml</source>
</tag>
</facelet-taglib>
As a side note, tag libraries can either be placed in the META-INF directory of your jar (same as a faces-config.xml), or specified in your application's web.xml.
That's it for now, more to come soon!
10 Comments:
Jacob, what is the object model for these features? For example, when I define a tag or a template, can I access them as JSF components? And if so, how?
By Anonymous, at 5:31 PM
Kito, all of the ui tags do not have any state within the component tree. They only exist within the document in order to dictate the tree creation process.
I've been working on a ui:component tag that *will* act as a placeholder within the document that can be bound to the component tree or managed beans.
By Jacob Hookom, at 10:18 PM
Hi Jacob,
facelets is great so far. I really, REALLY want to use it.
Couple of issues which are probably not directly facelets, but if you could spare a moment for an opinion or a pointer I'd really appreciate it.
I upgraded my setup from JSP/JSF RI to use Facelets and MyFaces.
Things were going fine until I ported a MyFaces component, the Newspaper Table. This is a modified data table which uses a var attribute, a la:
<x:newspaperTable id="docTypeGrid" newspaperColumns="4" value="#{MainPageBean.documentTypes}"
var="docType">
However, for whatever reason I get:
WARN VariableResolverImpl:348 - Variable 'docType' could not be resolved.
This worked fine in the JSP/JSF RI configuration.
I tested the same scenario with a straight dataTable in facelets and this works as expected.
Any clues or pointers?
(Also, while I'm here, do you have an idea of how to use Eclipse WTP effectively with facelets? The code complete for XML tags disappeared when moving to the xhtml file format. It seems to only be supported in the JSP editor, not the HTML editor, even if using xhtml.)
By Red3, at 11:04 AM
OK, I've worked out that the xmlns for the MyFaces extensions is not getting resolved, the jsf tag is just getting passed through to the page untouched.
Here's the namespace declaration:
xmlns:x="http://myfaces.apache.org/extensions"
This worked fine in the JSP, and all other namespaces are resolving in the facelet xhtml file. Any ideas?
By Red3, at 12:21 PM
Hi Jacob,
I've getting through Facelets and I'd like to post you a question.
I'd like to define a tag-source containing
<h:commandLink value="#{value}" action="#{action}"/>
where value and action represent the tag parameters.
Unfortunately this doesn't work because of problem con EL resolver on the action attribute.
Is there any workaround?
Thanks.
Marco
By Anonymous, at 4:01 AM
Hello Jacob :)
I'm wondering how the multi-level templating will look like. I would like to use template inclusion in another template and manage a Member and Guest templates, The member is included in the guest template and provides more functionalities to the user ... can you help me out with a simple example :)
Thanks in advance :)
KKirov
By Anonymous, at 11:40 AM
Hello Jacob,
What about attribute templating let's have an example:
Say we have a redundent code snippet
HTML is not allowed so I will use these caracters '[]' instead:
[tc:box label="my box"]
[f:facet name=layout]
[tc:gridLayout columns="*;*"/]
[/f:facet]
[/tc:box]
we want to have a single template
[my:box columns="*;*" label="mybox" id="hereWeAre"]
the id attribute is not mandatory, and when not specified it is generated but if we specify "" it is forbidden so we need to know if the id value is empty to decide whether to include the attribute declaration or not in the template.
You don't talk about how we do this!!!
Regards,
Zied Hamdi
By weally, at 5:55 AM
FREE PSP GAMES
By Anonymous, at 1:38 PM
情趣用品,情趣用品,情趣用品,情趣用品,情趣用品,情趣,情趣,情趣,情趣,情人歡愉用品,情趣用品,AIO交友愛情館,情人歡愉用品,美女視訊,情色交友,視訊交友,辣妹視訊,美女交友,嘟嘟成人網,按摩棒,震動按摩棒,微調按摩棒,情趣按摩棒,逼真按摩棒,G點,跳蛋,跳蛋,跳蛋,性感內衣,飛機杯,充氣娃娃,情趣娃娃,角色扮演,性感睡衣,SM,潤滑液,威而柔,香水,精油,芳香精油,自慰,自慰套,性感吊帶襪,情趣用品加盟,情人節禮物,情人節,吊帶襪,成人網站,AIO交友愛情館,情色,情色貼圖,情色文學,情色交友,色情聊天室,色情小說,七夕情人節,色情,A片,A片下載,免費A片,免費A片下載,情色電影,色情網站,辣妹視訊,視訊聊天室,情色視訊,免費視訊聊天,視訊聊天,美女視訊,視訊美女,美女交友,美女,情色交友,成人交友,自拍,本土自拍,情人視訊網,視訊交友90739,生日禮物,情色論壇,正妹牆,正妹,成人網站,A片,免費A片,A片下載,免費A片下載,AV女優,成人影片,色情A片,成人論壇,情趣,免費成人影片,成人電影,成人影城,愛情公寓,色情影片,保險套,舊情人,微風成人,成人,成人遊戲,成人光碟,色情遊戲,跳蛋,按摩棒,一夜情,男同志聊天室,肛交,口交,性交,援交,免費視訊交友,視訊交友,一葉情貼圖片區,性愛,視訊,嘟嘟成人網
愛情公寓,情色,舊情人,情色貼圖,情色文學,情色交友,色情聊天室,色情小說,一葉情貼圖片區,情色小說,色情,色情遊戲,情色視訊,情色電影,aio交友愛情館,色情a片,一夜情,辣妹視訊,視訊聊天室,免費視訊聊天,免費視訊,視訊,視訊美女,美女視訊,視訊交友,視訊聊天,免費視訊聊天室,情人視訊網,影音視訊聊天室,視訊交友90739,成人影片,成人交友,美女交友,微風成人,嘟嘟成人網,成人貼圖,成人電影,A片
By Anonymous, at 12:30 PM
Hi.
Very interesting, but I would like to ask about something about internationalization.
Usually the examples are header, left and main-content. If you put this into f:view with a locale works great. But how do you internationalize if you have another composition into main-content, its like recursive and everything is placed into a ui:decorate. In my application I can't be able to change the language in the inner templates.
I hope I have explained..
thanks
By Unknown, at 6:23 PM
Post a Comment
<< Home