I'm having a issue with PrimeFaces 3.4 and Facelets
I created a Facelets template with the following:
<?xml version='1.0' encoding='UTF-8' ?>
<h:head>
<h:outputStylesheet library="css" name="styles.css"></h:outputStylesheet>
</h:head>
<h:body>
<p:layout fullPage="true">
<p:layoutUnit position="north" size="200px" collapsible="true">
<ui:include src="header.xhtml"></ui:include>
</p:layoutUnit>
<p:layoutUnit position="south" size="50px" collapsible="true">
Sul
</p:layoutUnit>
<p:layoutUnit id="contentView" position="center">
<ui:insert name="content"></ui:insert>
</p:layoutUnit>
</p:layout>
</h:body>
My index.xhtml:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition template="./maintemplate.xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:define id="contentView" name="content">
<ui:include src="#{userController.currentPage}"></ui:include>
</ui:define>
</ui:composition>
So, the userController.currentPage contains at the beginning a login page that works with primeFaces componends.
When I click the menu that is available inside the header.xhtml I have the following:
<p:menuitem value="Tickets" actionListener="#{userController.setCurrentPage('tickets.xhtml')}" update=":contentView" ajax="false"></p:menuitem>
After clicking the center layout gets blank. I don't see any error or information that something is wrong.
I can render the page tickets.xhtml without any problem.
Any help is most appreciated.
I'm using Netbeans 7.3 RC1 - Apache Tomcat 7.0.34.0 / PrimaFaces 3.4 / JSF 2.1
EDIT: putting ajax="false" in the menu works, but it refreshed all page. Anyidea how I can make this work without having to refresh the full page, I would like to refresh just the center one.
finally managed to do it.
Found over here the following:
How to ajax-refresh dynamic include content by navigation menu? (JSF SPA)
based on the above answer I performed the following operations:
1.put the ajax tag and the menu inside it.
2. And this was also my mistake, change the ajax render from the <ui:layoutUnit> to <h:form>
3. removed all the h:form tags from the child xhtml as it is now included in the template file.
After this it works withoout any problem.
Related
I'm kinda new to the JSF and Web Programming, i'm using primefaces 6.0 and trying to have a TOP MENU, that opens TabView. Everytime that you select an option on the TOP MENU, opens a new Tab on the TabView with the content of that selected option.
I was searching but didn't found how to do it.
Thank you guys!
For starters I suggest you use the <p:layout>component to divide your page, and for displaying the content in tabs I suggest you use <ui:include>you can read about it here.
So your main page should look something like this :
<!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:p="http://primefaces.org/ui">
<h:head>
</h:head>
<body>
<p:layout>
<p:layoutUnit position="north">
<!-- !!!!!!!!!! Menu goes here !!!!!!!!!!! -->
</p:layoutUnit>
<p:layoutUnit position="center" resizable="false">
<p:tabView>
<p:tab title="Title goes here">
<ui:include src="content" />
</p:tab>
</p:tabView>
</p:layoutUnit>
</p:layout>
</body>
</html>
Note : In case you want to generate your tabs dynamically you'd want to create a custom Tab class and use JSTL's <c:forEach> to loop over the tabs to populate the tabView.
xhtml :
<p:tabView>
<c:forEach items="#{homeView.openTabs}" var="tab">
<p:tab title="#{tab.title}" closable="true" rendered="#{tab.open}">
<ui:include src="#{tab.content}"/>
</p:tab>
</c:forEach>
</p:tabView>
Note that openTabs is an ArrayList of Tabs.
Custom tab class :
public class Tab {
private String title;
private String content;
private boolean open;
//Custom constructor, getters and setters...
Tips :
Use the <p:tab> rendered attribute to handle closing and reopening tabs. Be sure to use tabView's custom event <p:ajax event="tabClose" listener="#{homeView.onTabClose}"/> for advanced event handling.
I have a working JSF page, but if I add xmlns:leaf="http://java.sun.com/jsf/composite/jsf2leaf" to it, and try to use any ot its tags, like <leaf:map center="42.120000,-72.540000" />, I get the following warning:
One or more resources have the target of 'head', but no 'head' component has been defined within the view.
Everything works fine, the map is there, I can add markers, but I can't get rid of the warning message.
My JSF page looks like this:
<?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:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui" xml:lang="hu" lang="hu"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:leaf="http://java.sun.com/jsf/composite/jsf2leaf"
>
<f:view contentType="text/html">
<f:metadata>
<f:viewAction action="#{dashboardController.readURLParam()}"/>
</f:metadata>
<h:head/>
<h:body>
...
<h:form>
...
<p:panel>
...
<c:forEach>
...
<p:panel>
<leaf:map center="42.120000,-72.540000" />
</p:panel>
</c:forEach>
</p:panel>
</h:form>
</h:body>
</f:view>
found the problem, it, in the jsf2leaf.jar the map.xhtml and advancedmap.xhtml uses <head></head> instead of <h:head></h:head>, changed it, repackaged the jar file, and it works fine
In my project I'm adding programmatically a composite component to a primefaces p:panel, as described here: How to programmatically or dynamically create a composite component in JSF 2 .
This is the composite component:
<?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:composite="http://java.sun.com/jsf/composite"
xmlns:p="http://primefaces.org/ui">
<composite:interface>
</composite:interface>
<composite:implementation>
<h:panelGroup styleClass="ui-grid ui-grid-responsive"
id="myPG" layout="block">
<div class="ui-grid ui-grid-responsive label-777777">
<div class="ui-grid-row">
<div class="ui-grid-col-11-5">
<label>#{msgs['label.content']}</label>
</div>
</div>
</div>
<p:commandButton styleClass="myButton blueButton"
id="myCompositeButton" value="#{msgs['button.elimina']}"
update="#form"
actionListener="#{myController.onMyClick}" />
</h:panelGroup>
</composite:implementation>
</html>
When added to the page, it show fine, but after the postback of the button, the "div" part, disappear (it isn't sent to the browser).
If I implements the div whith h:panelGroup and h:outputlabel, the elements get rendered but empty (#{msgs['label.content']} is void).
Here is the onMyClick handler (no logic in it):
public void onMyClick()
{
System.out.println("#########################################CALLBAK");
}
Where I'm wrong?
Primefaces version is 5.1, running on JBoss AS 7.1.1
As I was having problem to programmatically create a component on the target architecture (IBM WAS 8.5, with myfaces 2.0 and no, I can't change jsf implementation), I changed the approach, using backing bean bound ui:include inside an h:panelGroup
<h:panelGroup id="myPanel" layout="block" rendered="#{myController.moduleSelected }">
<ui:include src="#{myController.moduleType}"></ui:include>
</h:panelGroup>
Posting the answer to help other users
I cannot find out how navigate to page located in upper dir. Is it possible at all?
here is my project structure:
question:
how should line <ui:composition template="web2/web/index.xhtml"> looks like in the code of any page from folder main_pages to include index.xhtml and how to insert i.e. image from images folder (I can't get right path, io.exception still):
onas.xhtml
<?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"
>
<h:body>
<ui:composition template="web2/web/index.xhtml">
<ui:define name="centerContent">
<h:form>
<p:growl id="msg" showDetail="true" sticky="true" />
<p:panelGrid styleClass="myPanel">
<p:row>
<p:column>
<ui:param name="mainTag" value="Z chęcią odpowiemy" />
<h2>Zapytaj</h2>
<h4>#{mainTag}</h4></p:column>
</p:row>
<p:row>
<p:column><p:inputTextarea styleClass="myTextArea" autoResize="true" value="#{mySendBean.mailContent}"/></p:column>
<p:column>
<h:commandButton actionListener="#{mySendBean.sendMail2()}" value="Wyślij" update="msg">
</h:commandButton>
</p:column>
</p:row>
</p:panelGrid>
</h:form>
</ui:define>
</ui:composition>
</h:body>
</html>
when I change composition to be:
<ui:composition template="#{request.contextPath}/index.xhtml">
I get error:
/onas.xhtml #11,74 <ui:composition template="#{request.contextPath}/index.xhtml"> Invalid path : /web2/faces/index.xhtml
or if I add /faces/:
/onas.xhtml #11,74 <ui:composition template="#{request.contextPath}/faces/index.xhtml"> Invalid path : /web2/faces/index.xhtml
All paths in <ui:xxx> components are absolute to the webcontent root, which is the "Web Pages" folder. Also, you should prefer using absolute paths starting with / instead of relative paths.
So, this should do:
<ui:composition template="/index.xhtml">
The #{request.contextPath} is only necessary when you want to manually create an URL (for the enduser). The /faces is only necessary when you want to invoke the JSF mapping on it.
See also:
How to include another XHTML in XHTML using JSF 2.0 Facelets?
Unrelated to the concrete problem, it's recommended to put template files in /WEB-INF folder to prevent direct access.
See also:
Which XHTML files do I need to put in /WEB-INF and which not?
I am currently trying to insert pre-defined jsf pages into a particular portion of a main jsf page. I have been able to achieve this semi-successfully using the following:
public void includeFacelet(String pageString){
//NOTE SEE BELOW
centerPanelGrid.getParent().getChildren().clear();
centerPanelGrid.getChildren().clear();
String actualPath = "faceletFolder/".concat(pageString).concat(".xhtml");
try{
FacesContext facesContext = FacesContext.getCurrentInstance();
FaceletContext faceletContext = (FaceletContext)facesContext.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
faceletContext.includeFacelet(centerPanelGrid, actualPath);
}catch(IOException ex){
...
}
}
Where the centerPanelGrid is a field variable in my managed bean (dynamicComponentBean) which is bound to a HtmlPanelGrid within the main jsf page and the actualPath variable is the relative path indicating the location of the jsf page.
As for the note, it may seem like non-sense to have to have that line (trust me I realize that) however in all of my tests if I didn't have that line then when I went to include the jsf page it wouldn't include anything...
This is an outline of the main jsf page:
<?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:p="http://primefaces.org/ui">
<h:head>
<title>User Page</title>
</h:head>
<h:body>
<p:layout fullPage="true">
<p:layoutUnit position="north" size="45" header="header"/>
<p:layoutUnit position="south" size="100" resizable="true">
[Footer Text]
</p:layoutUnit>
<p:layoutUnit position="west" size="200" resizable="true">
[West Content]
</p:layoutUnit>
<p:layoutUnit position="east" size="200" resizable="true">
[East Content]
</p:layoutUnit>
<p:layoutUnit position="center" resizable="true" id="dynamicLayout">
<h:panelGrid id="dynamicContent" binding="#{dynamicComponentBean.centerPanelGrid}"/>
</p:layoutUnit>
</p:layout>
</h:body>
</html>
And a small example of a page that could get inserted into the centerPanelGrid would be as follws:
<?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:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Reports Interface</title>
</h:head>
<h:body>
<h:form>
<h:panelGrid columns="3" columnClasses="rightalign,leftalign,leftalign">
<h:outputText value="Find Daily Report"/>
<p:calendar id="dailyCalendar" value="#{reports.dailyDate}" mode="popup" effect="slide"/>
<h:commandButton id="findDailyReport" value="Search" action="#{dynamicComponentBean.includeFacelet('navString')}"/>
</h:panelGrid>
<h:message for="dailyCalendar"/>
</h:form>
</h:body>
</html>
With navString being whatever String I pass to it so that the includeFacelet method can pull the appropriate jsf to insert next.
My problem arises when I try to use the command button to navigate, it requires me to press it twice to work, the first press makes it seem like it refreshes the page or something and then the subsequent click allows me to include the correct facelet in the centerPanelGrid.
I have done extensive debugging on the issuse and I have found that during the first click it is making no calls to any method within any of my managed beans and is not actually going into any of my code for that matter. I have no idea why it is doing this or what I need to do to get it to just include the facelet that I want and have it navigate normally.
In essence these web pages come from an additional enterprise application that was developed seperately and integrated into the current system. The current system does all page generation through manually creating the java objects that represent all of the various UIComponents and putting them into their appropriate place. However short of creating seperate stateles session beans to generate all of these various pages in a similar fashion I have set it up to know when these pages from the integrated application are being called and to instead put them into the dynamic component panel using the includeFacelet method.
Try using
faceletContext.includeFacelet(centerPanelGrid.getParent(), actualPath);