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

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.

Related

How to use f:importConstants in composite component?

What is the best way to use f:importConstants inside of a composite component?
You can't place f:metadata there, so what is the best workaround here?
With Omnifaces and o:importConstants in JSF 2.2, that was no problem, it was allowed everywhere, even in composite component.
Thanks in Advance :)
Since <f:importConstants> must be a child of <f:metadata> (which in turn must be a child of <f:view>), it must use same compositing pattern as described in the official documentation:
The implementation must allow templating for this element according
to the following pattern.
template client XHTML view, view01.xhtml
<ui:composition template="template.xhtml">
<ui:define name="metadata">
<f:metadata>
<f:viewParam name="id"/>
</f:metadata>
</ui:define>
<ui:define name="content">
<h1>The big news stories of the day</h1>
</ui:define>
</ui:composition>
Note line 4. The page author must ensure that the <f:metadata> element does not
appear on a template or included page. It must reside on the root page that
corresponds to the viewId.
The template page, template.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xml:lang="en" lang="en">
<body>
<f:view>
<ui:insert name="metadata"/>
<div id="container">
<ui:insert name="content"/>
</div>
</f:view>
</body>
</html>

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>

How to get bean name dynamically [duplicate]

I have a Facelet that might be used in different applications.
I don't to copy it, but reuse it. I need to pass the backing bean that will manage the view as a parameter, as some logic may vary according to the application where it is used in.
I don't want to use a composite component, but just include the Facelet and specify which bean will manage the view. How can I achieve this?
Let me give an example:
<ui:composition template="/resources/common/templates/template.xhtml"
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:c="http://java.sun.com/jsp/jstl/core" xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich" xmlns:fn="http://java.sun.com/jsp/jstl/functions">
<ui:define name="content">
<!-- somehow establish the backing bean that will manage formView.xhtml -->
<!-- f:set assign="ParameterBean" value="#{Bean}" / -->
<ui:include src="formView.xhtml" />
</ui:define>
</ui:composition>
formView.xhtml :
<ui:composition template="/resources/common/templates/template.xhtml"
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:c="http://java.sun.com/jsp/jstl/core" xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich" xmlns:fn="http://java.sun.com/jsp/jstl/functions">
<ui:define name="content">
<h:outputText value="#{ParameterBean.texto}" />
</ui:define>
</ui:composition>
You can use <ui:param> for that. It needs to be nested in the <ui:include>.
<ui:include src="formView.xhtml">
<ui:param name="ParameterBean" value="#{Bean}" />
</ui:include>
Unrelated to the concrete problem, standard Java Naming Conventions state that instance variable names must start with lower case. You should change your code in such way that respectively parameterBean and #{bean} will be used.
Because I would have found it helpful yesterday, when I was looking for this, here is a simple version of how to do this, without the extraneous template, defines and namespaces:
File1.xhtml (the root tag doesn't matter)
<ui:include src="File2.xhtml">
<ui:param name="person" value="#{whatever_value_you_want_to_pass}" />
</ui:include>
File2.xhtml
<ui:composition ... xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets" ... >
<h:outputLabel value="#{person.name}" />
</ui:composition>
You can also nest further in the same manner.
File1.xhtml
<ui:include src="File2.xhtml">
<ui:param name="person" value="#{whatever_value_you_want_to_pass}" />
</ui:include>
File2.xhtml
<ui:composition ... xmlns:ui="http://java.sun.com/jsf/facelets" ... >
<ui:include src="File3.xhtml">
<ui:param name="name" value="#{person.name}" />
</ui:include>
</ui:composition>
File3.xhtml
<ui:composition ... xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets" ... >
<h:outputLabel value="#{name.length}" />
</ui:composition>

How do I include a body into a tagfile

I have a tagfile I intend to use as an input template:
<ui:composition
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<div class="qr">
<label>#{question}</label>
<div class="helpButton"></div>
<!-- body here -->
<!-- errors output eventually to go here -->
</div>
</ui:composition>
It is stored in my /WEB-INF/tags folder with a .taglib.xml and necessary web.xml context-param.
I understand it could be used as follows:
<g:question question="What is your name?" id="firstname">
<h:inputText value="#{bean.firstname}" />
</g:question>
at the moment this is in its most basic form. I intend to use various and complex inputs. but the layout of the label etc will always need to stay the same.
How do I include the body of the <g:question> in the tagfile?
Use <ui:insert>.
<ui:composition
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<div class="qr">
<label>#{question}</label>
<div class="helpButton"></div>
<ui:insert />
<!-- errors output eventually to go here -->
</div>
</ui:composition>
Do note that you can even use <ui:define name="..."> and <ui:insert name="..."> on tagfiles like as you usually do on templates.

How to include common content into multiple level template page

I am trying include a common page into a template but all I get is a blank page without error.
common.xhtml actually has the content that indicate in the template.xhtml. It seems the template.xhtml doesn't recognize the two level include.
template.xhtml
<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:s="http://jboss.com/products/seam/taglib"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:ub="http://jboss.com/products/seam/ub-taglib"
xmlns:rich="http://richfaces.ajax4jsf.org/rich">
<head>
<ui:insert name="css" />
<ui:insert name="header" />
</head>
<body>
<ui:insert name="body" />
</body>
</html>
custom.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
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:rich="http://richfaces.ajax4jsf.org/rich"
xmlns:a4j="https://ajax4jsf.dev.java.net/ajax"
xmlns:c="http://java.sun.com/jstl/core"
template="template.xhtml">
<ui:define name="css">
<link rel="stylesheet" type="text/css" href="/custom.css/>
</ui:define>
<ui:include src="common.xhtml" />
</ui:composition>
common.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
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:rich="http://richfaces.ajax4jsf.org/rich"
xmlns:a4j="https://ajax4jsf.dev.java.net/ajax"
xmlns:c="http://java.sun.com/jstl/core"
template="template.xhtml">
<ui:define name="header">
<h1>header</h1>
</ui:define>
<ui:define name="body">
<table><tr><td>Table</td></tr></table>
</ui:define>
</ui:composition>
This indeed won't work. The <ui:define> is supposed to be used in a template client (i.e. a page with <ui:composition template="...">), not in an include file (i.e. a page with <ui:composition> without template). You can however just "extend" from existing master templates.
Remove from custom.xhtml:
<ui:include src="common.xhtml" />
Change in common.xhtml
template="custom.xhtml"
And open common.xhtml instead of custom.xhtml in browser.
See also:
How to include another XHTML in XHTML using JSF 2.0 Facelets?
Unrelated to the concrete problem, to prevent the enduser form being able to open custom.xhtml or template.xhtml directly in browser, it's recommended to move them into the /WEB-INF folder. Further, are you aware of the <h:head> and <h:outputStylesheet> components? I suggest to make use of them. Also, having a <h1> to ultimately end up in <head> makes no sense. Perhaps you meant the <ui:insert name="header"> to be inside <body>? Further, you could easily put that <h1> in the template so that you don't need to repeat them in every template client.
/WEB-INF/templates/template.xhtml
<html ...>
<h:head>
</h:head>
<h:body>
<ui:insert name="header" />
<ui:insert name="body" />
</body>
</html>
/WEB-INF/templates/custom.xhtml (CSS file is placed in /resources folder)
<ui:composition ... template="/WEB-INF/templates/template.xhtml">
<ui:define name="header">
<h1><ui:insert name="custom-header" /></h1>
</ui:define>
<ui:define name="body">
<h:outputStylesheet name="custom.css" target="head" />
<ui:insert name="custom-body" />
</ui:define>
</ui:composition>
/page.xhtml
<ui:composition ... template="/WEB-INF/templates/custom.xhtml">
<ui:define name="custom-header">
header
</ui:define>
<ui:define name="custom-body">
<table><tr><td>Table</td></tr></table>
</ui:define>
</ui:composition>
See also:
Which XHTML files do I need to put in /WEB-INF and which not?
How to reference CSS / JS / image resource in Facelets template?

Resources