Why is ui:fragement not rendered inside ui:composition - jsf

I'm a beginner with JSF and Java, please be nice!
I'm trying to render a specific block if a user is an Administrator.
I have a template. This template render correctly a specific block if the user is logged.
admin.xhtml:
<ui:composition template="../../WEB-INF/tpl/admin/template.xhtml">
<ui:define name="sectionTitle">Admin</ui:define>
<!-- Logged as Admin -->
<ui:fragment rendered="#{user.admin}">
<ui:define name="body">
<h3>Welcome</h3>
<p>Please choose an administration task!</p>
</ui:define>
</ui:fragment>
</ui:composition>
template.xhtml:
<div class="header">
<h2>
<ui:insert name="sectionTitle"> Default Section Title</ui:insert>
</h2>
<ui:insert name="logBox">
<ui:fragment rendered="#{not user.logged}">
<ui:include src="login.xhtml"></ui:include>
</ui:fragment>
<ui:fragment rendered="#{user.logged}">
<h:form>
<h:commandButton value="Logout"
action="#{userService.logout}" />
</h:form>
</ui:fragment>
</ui:insert>
</div>
<div class="corebody">
<ui:insert name="body"> Default Section Content</ui:insert>
</div>
I can move the rendered block inside the template like so:
<ui:fragment rendered="#{user.admin}">
<ui:insert name="body"> Default Section Content</ui:insert>
</ui:fragment>
but this don't seem ok to me regarding the responsability of each files ( this don't seem really generic, why should such a thing be in the template? ).
Am I missing something really obvious?

Anything outside <ui:define> and <ui:composition> is ignored during building the view and don't end up in JSF component tree.
You need to put <ui:fragment> inside <ui:define>.
<ui:composition template="../../WEB-INF/tpl/admin/template.xhtml">
<ui:define name="sectionTitle">Admin</ui:define>
<!-- Logged as Admin -->
<ui:define name="body">
<ui:fragment rendered="#{user.admin}">
<h3>Welcome</h3>
<p>Please choose an administration task!</p>
</ui:fragment>
</ui:define>
</ui:composition>
An alternative is to use JSTL <c:if> as that runs during view build time already:
<ui:composition template="../../WEB-INF/tpl/admin/template.xhtml">
<ui:define name="sectionTitle">Admin</ui:define>
<!-- Logged as Admin -->
<c:if test="#{user.admin}">
<ui:define name="body">
<h3>Welcome</h3>
<p>Please choose an administration task!</p>
</ui:define>
</c:if>
</ui:composition>
See also:
How to include another XHTML in XHTML using JSF 2.0 Facelets?
JSTL in JSF2 Facelets... makes sense?

<ui:composition template="../../WEB-INF/tpl/admin/template.xhtml">
<ui:define name="sectionTitle">
<!-- Logged as Admin -->
<ui:fragment rendered="#{user.admin}">
<ui:define name="body">
<h3>Welcome</h3>
<p>Please choose an administration task!</p>
</ui:define>
</ui:fragment>
</ui:define>
</ui:composition>
Try this.

Related

Shared template form JSF

Is it possible to share this template in multipile components in same scope? I got an error because of duplicated ID, but I need this ID for updating / processing form, also for displaying messages
<ui:define name="content">
<h:form id="contentForm"
prependId="false"
enctype="multipart/form-data">
<p:messages showDetail="true"
closable="true">
<p:autoUpdate/>
</p:messages>
<ui:insert name="formContent" />
</h:form>
</ui:define>

How can I switch between two ui:compositions in a Facelets file?

In a JSF xhtml file, I would like to be able to choose between two different ui:compositions based on some flag. This is illustrated below using a fictional magic:if tag. How can I do this? In other words, what real tag can I use in place of magic:if?
<magic:if test="showOption1">
<ui:composition template="/option1.xhtml">
<ui:define name="header">Foo</ui:define>
</ui:composition>
</magic:if>
<magic:if test="!showOption1">
<ui:composition template="/option2.xhtml">
<ui:define name="header">Foo</ui:define>
</ui:composition>
</magic:if>
In other words, what real tag can I use in place of magic:if?
There's none. The <ui:composition> is the root element. Nothing can end up higher.
You have 2 options:
Do the switch in template attribute itself.
<ui:composition template="/option#{showOption1 ? 1 : 2}.xhtml">
<ui:define name="header">Foo</ui:define>
</ui:composition>
Use <ui:decorate> inside <ui:composition> instead, this one can be wrapped in a <c:if>.
<ui:composition template="/options.xhtml">
<c:if test="#{showOption1}">
<ui:decorate template="/option1.xhtml">
<ui:define name="header">Foo</ui:define>
</ui:decorate>
</c:if>
<c:if test="#{not showOption1}">
<ui:decorate template="/option2.xhtml">
<ui:define name="header">Foo</ui:define>
</ui:decorate>
</c:if>
</ui:composition>

p:dataTable does not render inside carousel and tab components

Environment:
- PrimeFaces version: 5.0
I'm trying to include a p:carousel
in my application, but the p:dataTable appears as a blank in the p:tab view. The following is a simplified example. The facelets template page is:
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<h:outputStylesheet name="./css/default.css"/>
<h:outputStylesheet name="./css/cssLayout.css"/>
<h:outputStylesheet name="./css/style.css"/>
<title>Test Template</title>
</h:head>
<h:body>
<div id="content" class="center_content">
<ui:insert name="content">Content</ui:insert>
</div>
</h:body>
The carousel JSF page:
<body>
<ui:composition template="./ClientNav.xhtml">
<ui:define name="content">
<h:form>
<p:carousel numVisible="1" autoPlayInterval="20000" effect="easeInStrong"
headerText="Contents" style="margin-bottom: 0" circular="true">
<p:tab>
<h1>Heading</h1>
<p>Text of the first tab view</p>
<p:graphicImage name="images/enterBlank.jpg" alt="sky" width="1000" height="252"/>
</p:tab>
<p:tab>
<p:dataTable value="#{topicbean.pubTopList}" var="top">
<p:column>
<p:commandLink value="#{top.topicname}" action="#{topicbean.searchGuestItems}"
ajax="false"/>
</p:column>
</p:dataTable>
</p:tab>
</p:carousel>
</h:form>
</ui:define>
</ui:composition>
</body>
If i replace p:dataTable with h:dataTable it renders perfectly. I also tested an ordinary JSF page (without templating) using the p dataTable and the same problem (no rendering) happened. Finally I tried to strip the carousel component to the bare minimum (in case any setting were causing css conflict):
<p:carousel numVisible="1">
tabs here
</p:carousel>
I'm not sure if this is a bug or I'm missing something in my code or how I'm using the carousel. Would appreciate any guidance. Thank you.

Test if a jsf template facelet content is defined by a template client using ui:define [duplicate]

I am wondering if it is possible to know if ui:insert was defined in the ui:composition.
I know that I can do it using separate ui:param, but just wanted to do it without in order to keep it simple and less error prone.
Example :
Template
...
<ui:insert name="sidebar" />
<!-- Conditionnaly set the class according if sidebar is present or not -->
<div class="#{sidebar is defined ? 'with-sidebar' : 'without-sidebar'}">
<ui:insert name="page-content" />
</div>
...
Page 1
...
<ui:define name="sidebar">
sidebar content
</ui:define>
<ui:define name="page-content">
page content
</ui:define>
...
Page 2
...
<ui:define name="page-content">
page content
</ui:define>
...
ui:param is for me the best way to go. It's just a matter of using it the right way. As a simple example, I define a param here to specify wether there's a sidebar or not. Keep in mind you can define a default insertion definition in the template, so just declare it inside:
template.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
<ui:insert name="sidebar">
<!-- By default, there's no sidebar, so the param will be present.
When you replace this section for a sidebar in the client template,
the param will be removed from the view -->
<ui:param name="noSideBar" value="true" />
</ui:insert>
<div class="#{noSideBar ? 'style1' : 'style2'}">
<ui:insert name="content" />
</div>
</ui:composition>
Then couple of views here, one using the sidebar and the other with no sidebar. You can test it and see how the style changes in the browser. You'll notice there's no value for #{noSideBar} in the second one, which will evaluate to false in any EL conditional statement.
page1.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets" template="/template.xhtml">
<ui:define name="content">
No sidebar defined? #{noSideBar}
</ui:define>
</ui:composition>
page2.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets" template="/template.xhtml">
<ui:define name="sidebar" />
<ui:define name="content">
No sidebar defined? #{noSideBar}
</ui:define>
</ui:composition>
This way you only need to worry about including the sidebar or not in the client view.

JSF Primefaces left, center layout

I don't understand how to display in center screen when I click button in my "left" menu.
Now I have that when I click button in my "left" menu, new page opens without "left" menu but I don't want it, I need that "left" menu wasn't disappeared.
Below is my code.
<h:head>
<title>Facelet Title</title>
</h:head>
<frameset rows="65,*" frameborder="0">
<frame scrolling="no" src="header.xhtml"/>
<frameset cols="200,*" frameborder="0">
<frame scrolling="no" src="menu.xhtml"/>
</frameset>
</frameset>
Basically, you need to give the target frame a name and specify it in the target attribute of the <a> element. E.g.
<frame name="center">
with
<a href="page.xhtml" target="center">
But this all is not entirely the right way to template a modern web application. Framesets have many disadvantages as to user experience and SEO valuability. Instead, the include and templating facilities of any server side view technology (like Facelets as you're using) should be used. Framesets should only be used when you have absolutely no server server side view technology at hands (thus, just plain HTML) or when you want to present an external website.
With Facelets, you should instead be using something like this as master template
/WEB-INF/templates/layout.xhtml
<!DOCTYPE html>
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title><ui:insert name="title">Default title</ui:insert></title>
</h:head>
<h:body>
<div id="header"><ui:include src="/WEB-INF/includes/header.xhtml"></div>
<div id="menu"><ui:include src="/WEB-INF/includes/menu.xhtml"></div>
<div id="content"><ui:insert name="content">Default content</ui:insert></div>
</h:body>
</html>
(you can use CSS to position the layout components the way you want, e.g. float:left on #menu and #content)
And this is how the template client (the page which you actually opens by URL) should look like:
/page.xhtml
<ui:composition template="/WEB-INF/templates/layout.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:define name="title">
New page title here
</ui:define>
<ui:define name="content">
<h1>New content here</h1>
<p>Blah blah</p>
</ui:define>
</ui:composition>
For an open source example of a modern JSF/Facelets web application, check among others the OmniFaces showcase application.
As you're using PrimeFaces, there's another alternative, the <p:layout>. See the "full examples" at its showcase application, for example this one.
See also:
Java EE 6 tutorial - Facelets
Your description is a bit confusing, but I imagine that JSF templating system is what you are after, enabling you to include the same code (a menu for example) on multiple pages. Frames are very outdated and largely not used anymore.
See example at http://www.mkyong.com/jsf2/jsf-2-templating-with-facelets-example/
As a further comment, this issue does not seem to be related to Primefaces (which is a component pack, none of these comments are included in your code).
Here is a simple header, page(s), footer example. You can use one form id for all believe it or not. The header goes in WebContent/templates. The other .xhtml can go in WebContent. If your #ManagedBean String method returns "second", the page second.xhtml will be displayed. Each pages still talks to it's own #ManagedBean.
<body">
<f:view>
<div id="container">
<h:form id="templateForm">
<div id="header">
<ui:include src="header.xhtml" />
</div>
<div id="wrapper">
<div id="firstId">
<ui:insert name="first"></ui:insert>
</div>
<div id="secondId">
<ui:insert name="second"></ui:insert>
</div>
<div id="inputMaskId">
<ui:insert name="inputMask"></ui:insert>
</div>
<div id="valtestId">
<ui:insert name="valtest"></ui:insert>
</div>
</div>
<div id="footer">
<ui:include src="footer.xhtml" />
</div>
</h:form>
</div>
</f:view>
</body>
We can use Layouts instead
include namespace
xmlns:p="http://primefaces.org/ui"
<p:layout fullPage="true">
<p:layoutUnit position="north" size="100" header=
"Top" resizable="true" closable="true" collapsible="true">
<h:outputText value="Layout content for North" />
</p:layoutUnit>
<p:layoutUnit position="south" size="100" header="Bottom"
resizable="true" closable="true" collapsible="true">
<h:outputText value="Layout content for South" />
</p:layoutUnit>
<p:layoutUnit position="west" size="200" header=
"Left" resizable="true" closable="true" collapsible="true">
<h:outputText value="Layout content for West" />
</p:layoutUnit>
<p:layoutUnit position="east" size="200" header=
"Right" resizable="true" closable="true" collapsible="true">
<h:outputText value="Layout content for Right" />
</p:layoutUnit>
<p:layoutUnit position="center">
<h:outputText value="Layout content for Center" />
</p:layoutUnit>
</p:layout>
This will render five panels

Resources