Overriding <ui:define> - jsf-2

Is there a way to override the <ui:define> that JSF templating offers?
For instance file main.xhtml, that includes a template file, contains:
<ui:define name="title">SomeTitle</ui:define>
<ui:define name="menu"><ui:include src="path_to_menu_1"/></ui:define>
<ui:define name="content">content_code_goes_here</ui:define>
If I want to create a main2.xhtml file that is identical to the main.xhtml, with the exception that it uses a different menu is there the possibility to do something like this:
<ui:include src="main.xhtml"/>
<ui:define name="menu"><ui:include src="path_to_menu_2"/></ui:define>
Where the <ui:define name="menu"> overrides the tag with the same name attribute in main.xhtml

Just specify main.xhtml as template of main2.xhtml.
main.xhtml
<ui:composition template="sometemplate.xhtml" ...>
<ui:define name="title">SomeTitle</ui:define>
<ui:define name="menu"><ui:include src="path_to_menu_1"/></ui:define>
<ui:define name="content">content_code_goes_here</ui:define>
</ui:composition>
main2.xhtml
<ui:composition template="main.xhtml" ...>
<ui:define name="menu"><ui:include src="path_to_menu_2"/></ui:define>
</ui:composition>

Related

JSF Bookmarkable URL to update ui:decorate value

Need help here. I'm trying to make my current project bookmarkable. My current design can basically be summed up in this code snippet:
<?xml version="1.0" encoding="UTF-8"?>
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<f:metadata>
<f:viewParam name="contentUrl" value="#{navigationBean.contentUrl}"/>
</f:metadata>
<h:body>
<ui:composition template="/views/template/template.xhtml">
<ui:define name="leftpane">
<ui:include src="/views/admin/menu_administrator.xhtml"/>
</ui:define>
<ui:define name="rightpane">
<p:growl showDetail="true" sticky="false" />
<ui:decorate template="/views/admin/content/#{navigationBean.contentUrl}.xhtml"/>
</ui:define>
</ui:composition>
</h:body>
</html>
So I have this template to make the site 30/70 look having the "leftpane" contain the menu and the "rightpane" to display the output content. What I want is to be able to change the output in the "rightpane" depending on the URL sent:
www.mysite.com/projectitle/views/admin/Administrator.xhtml?faces-redirect=true&contentUrl=cont_admin_rapptmnttype
Whatever will be constructed in this url: /views/admin/content/#{navigationBean.contentUrl}.xhtml on the "rightpane" also has a corresponding backing bean to generate the needed output
I'm using Primefaces3.5, MyFaces2.0, WAS8.5
Hope someone could help me out on this. Thanks.
UPDATE:
I am using a p:menuitem to set the contentUrl like
<p:menuitem value="Appointment Type" id="cont_admin_rapptmnttype"
ajax="false" outcome="#{navigationBean.currentMode}" >
<f:param name="contentUrl" value="cont_admin_rapptmnttype"/>
</p:menuitem>
But when I click on the menuitem I get a Stackoverflow exception which, as it turns, is caused by:
<ui:decorate template="/views/admin/content/#{navigationBean.contentUrl}.xhtml"/>
Which is the one I'm trying to update.
Here is the recurring exception in the stacktrace:
at org.apache.myfaces.view.facelets.tag.ui.DecorateHandler.apply(DecorateHandler.java:137)
at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:51)
at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:59)
at org.apache.myfaces.view.facelets.tag.jsf.ComponentTagHandlerDelegate.apply(ComponentTagHandlerDelegate.java:324)
at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:54)
at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:51)
at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:59)
at org.apache.myfaces.view.facelets.tag.jsf.ComponentTagHandlerDelegate.apply(ComponentTagHandlerDelegate.java:324)
at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:54)
at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:51)
at org.apache.myfaces.view.facelets.tag.ui.CompositionHandler.apply(CompositionHandler.java:150)
at org.apache.myfaces.view.facelets.compiler.NamespaceHandler.apply(NamespaceHandler.java:57)
at org.apache.myfaces.view.facelets.compiler.EncodingHandler.apply(EncodingHandler.java:45)
at org.apache.myfaces.view.facelets.impl.DefaultFacelet.include(DefaultFacelet.java:322)
at org.apache.myfaces.view.facelets.impl.DefaultFacelet.include(DefaultFacelet.java:369)
at org.apache.myfaces.view.facelets.impl.DefaultFacelet.include(DefaultFacelet.java:347)
at org.apache.myfaces.view.facelets.impl.DefaultFaceletContext.includeFacelet(DefaultFaceletContext.java:215)

Passing the backing bean as a parameter to a Facelet include

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 should I use Primefaces Dock component?

I'm trying to use dock menu, but it doesn't work. (it shows the images but it doesn`t zoom on them when I move the mouse over it). I want to use it in the center layout-unit of my page, inserting another page which acctualy contains the dock. The code looks like this:
template.xhtml
<!DOCTYPE html>
<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:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<style type="text/css">
body.ui-layout-container { background-color: cadetblue;}
</style>
</h:head>
<h:body>
<p:layout fullPage="true" resizeTitle="resize">
<p:layoutUnit position="north" id="north" resizable="false" size ="75">
<ui:include src="header.xhtml" />
</p:layoutUnit>
<p:layoutUnit position="west" id="west" resizable="false" style="height:580px;overflow:hidden;" size="180">
<ui:include src="menu.xhtml" />
</p:layoutUnit>
<**p:layoutUnit styleClass="layoutUnitCenter" position="center">
!!Here I insert the page which contains the dock
<ui:insert name="content" />
</p:layoutUnit>**
<p:layoutUnit position="south" resizable="true" id="south" size="40">
<ui:include src="footer.xhtml" />
</p:layoutUnit>
</p:layout>
</h:body>
</html>
dock.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"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
template="template.xhtml">
<ui:define name="content">
<h:head>
</h:head>
<h:body>
<h:form>
<p:dock position="top">
<p:menuitem value="teachers" icon="/images/dock/teacher.png" url="#"/>
<p:menuitem value="students" icon="/images/dock/student.png" url="#"/>
<p:menuitem value="parents" icon="/images/dock/parent.png" url="#"/>
</p:dock>
</h:form>
</h:body>
</ui:define>
</ui:composition>
I tried to use the dock.xhtml by itself, without the ui:composition and it works just fine. But when I try to use it like this, it only shows the images, but doesnt do anything when I move the mouse over the images. Another problem is that it doesnt put the dock in the center of the area. It positions it a little to the left.
I`m pretty new to jsf and Primefaces, so any answer might help.
This code generate the same issue you asked help for:
This little change, solved for me:

JSF2: Tag Library supports namespace: http://java.sun.com/jsf/composite/components/customer, but no tag was defined for name: list

I created a composite component for a list of customers. I can use this component in a view:
<html 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"
xmlns:p="http://primefaces.org/ui"
xmlns:customer="http://java.sun.com/jsf/composite/components/customer">
<ui:composition template="/WEB-INF/templates/template.xhtml">
<ui:define name="caption">
<h:outputText value="#{msg.customerListHeading}" />
</ui:define>
<ui:define name="content">
<ui:decorate template="/WEB-INF/templates/sidebox.xhtml">
<ui:param name="title" value="#{msg.customerListHeading}" />
<p:outputPanel>
<h:form id="customerList">
<customer:list list="#{customerControllerBean.list}">
<f:facet name="headerButton">
<h:button outcome="customerdetail.jsf"
value="#{msg.newButtonLabel}" />
</f:facet>
<f:facet name="rowButton">
<h:commandButton value="#{msg.deleteButtonLabel}"
action="#{customerControllerBean.delete(customer)}" />
<h:button outcome="customerdetail.jsf?id=#{customer.id}"
value="#{msg.editButtonLabel}" />
</f:facet>
</customer:list>
</h:form>
</p:outputPanel>
</ui:decorate>
</ui:define>
</ui:composition>
</html>
But when i use the component in a very similar view i get the following error:
<customer:list> Tag Library supports namespace: http://java.sun.com/jsf/composite/components/customer, but no tag was defined for name: list
The problematic view looks as follows:
<html 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"
xmlns:p="http://primefaces.org/ui"
xmlns:customer="http://java.sun.com/jsf/composite/components/customer">
<ui:composition template="/WEB-INF/templates/template.xhtml">
<ui:define name="caption">
<h:outputText value="#{msg.customerListHeading}" />
</ui:define>
<ui:define name="content">
<ui:decorate template="/WEB-INF/templates/sidebox.xhtml">
<ui:param name="title" value="#{msg.customerListHeading}" />
<p:outputPanel>
<h:form id="customerList">
<customer:list list="#{customerControllerBean.list}">
<f:facet name="rowButton">
<h:commandButton value="#{msg.applyButtonLabel}"
action="#{orderControllerBean.setCustomer(customer)}" />
</f:facet>
</customer:list>
</h:form>
</p:outputPanel>
</ui:decorate>
</ui:define>
</ui:composition>
</html>
As u can see the two view differs only by the facets i use to add buttons to the customer list table as i use the list in two different contexts. But why does the second view not work?
I found that there is/was an issue with Mojarra, but i use the so called stable revision regarding this problem:
2012-09-16 19:09:41,512 INFO [javax.enterprise.resource.webcontainer.jsf.config] (MSC service thread 1-4) Mojarra 2.1.7-jbossorg-1 (20120227-1401)
i found a workaround for this problem on Mojarra Jira:
http://java.net/jira/browse/JAVASERVERFACES-2437
i placed the xmlns:customer="http://java.sun.com/jsf/composite/components/customer" in the ui:composition tag and the view rendered sucessfully:
<html 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"
xmlns:p="http://primefaces.org/ui"
xmlns:customer="http://java.sun.com/jsf/composite/components/customer">
<ui:composition template="/WEB-INF/templates/template.xhtml" xmlns:customer="http://java.sun.com/jsf/composite/components/customer">
<ui:define name="caption">
<h:outputText value="#{msg.customerListHeading}" />
</ui:define>
<ui:define name="content">
...
According to that Jira the problem is fixed in Mojarra 2.1.10, so i hope JBoss updates AS 7.1 soon... :)
Incorrect folder path (components) is viewed by eclipse
Remove src/main/resource from build path -- Build Path==> Remove from Build Path.
And add again in build path

How to use <f:loadBundle> tag inside <ui:composition> tag

I want to use <f:loadBundle> tag in my view. I know that I can declare it inside faces-config.xml, but for a reason I want to use it in my view. I am using the tag in this manner but it is not working. I am using it inside <ui:composition> tag.
<h:head>
<title>Email Content</title>
</h:head>
<h:body>
<ui:composition template="./WEB-INF/templates/layout.xhtml">
<ui:define name="content">
<f:loadBundle basename="presentationBeans.homepage.messages" var="msgs"/>
<h:form id="emailContent_Review" >
<p:growl id="growl" showDetail="true" />
<p:panel id="panel"
header="#{msgs.ECR_panelHeader}"
style="border-color: #000000;width: 960px;position: absolute;left: 150px;height: 370px" >
<p:dataTable value="#{emailContent_Review.emailContent}"
var="emailContent"
selection="#{emailContent_Review.selectedEmailContent}"
emptyMessage="#{msgs.ECR_tableEmptyMessage}"
widgetVar="portalsTable"
rows="8" height="350" paginator="true">
<f:facet name="header" >
</f:facet>
</p:dataTable>
</p:panel>
</h:form>
</ui:define>
</ui:composition>
</h:body>
What I am doing wrong? Also I read that
To make use of a template, you use a 'ui:composition' tag with a 'template' attribute.
Facelets removes all tags outside the tag - that is, the doctype declaration, html, head, title and body tags. This is necessary because the <ui:composition> is replaced with the template that contains its own set of html, head, title, and body tags.
If I want to use my properties file in the head section, then how can I use it? Because head section is outside the <ui:composition> tag. I mean to say, if I want to do this
<h:head>
<title>#{msgs.indexWindowTitle}</title>
</h:head>
then how can I use my properties file outside <ui:composition>?
This is indeed not going to work. Change your master template layout.xhtml to replace the title by a template insert placeholder:
<h:head>
<title><ui:insert name="title">Default title</ui:insert></title>
</h:head>
Then change your template client to define it:
<ui:composition template="./WEB-INF/templates/layout.xhtml">
<ui:define name="title">
<f:loadBundle basename="presentationBeans.homepage.messages" var="msgs"/>
#{msgs.indexWindowTitle}
</ui:define>
<ui:define name="content">
...
</ui:define>
</ui:composition>
Note that you don't need to repeat the <f:loadBundle> for <ui:define name="content">.
I have struck upon an approach that works well for me on Mojarra 2.1.x, perhaps give it a tumble. Tweaking #BalusC's example:
<ui:composition>
<f:loadBundle basename="presentationBeans.homepage.messages" var="msgs"/>
<ui:decorate template="./WEB-INF/templates/layout.xhtml">
<ui:define name="title">
#{msgs.indexWindowTitle}
</ui:define>
<ui:define name="content">
...
</ui:define>
</ui:decorate>
</ui:composition>
My approach of nesting the templated ui:decorate within my bare ui:composition tags works well for me because I often want to declare one f:loadBundle tag that is shared by all of my nested ui:define's. Not sure what kinds of extra machinations I'm making the kernel do when I do this however, or if I'm exploiting an incomplete implementation of the spec to get what I want. YMMV

Resources