Dynamic Tabs by selecting the option on Menu - jsf

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.

Related

Primefaces fileupload is not opening "file choose dialog" on IE9

I see abnormal behavior of fileUpload component on IE9 (it wokrs well on Chrome & Mozilla). When p:fileUpload is put p:dialog, file chooser dialog is not opened unless user double clicked the button, this behaviour on IE<=9 only.
Very simple code sample:
FileUploader.xhtml
<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:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head></h:head>
<h:body>
<p:commandButton onclick="PF('dlg').show()" value="open"></p:commandButton>
<h:form enctype="multipart/form-data">
<p:dialog widgetVar="dlg">
<p:growl id="messages" showDetail="true" />
<p:fileUpload value="#{UtilityView.file}" mode="simple" skinSimple="true" />
</p:dialog>
</h:form>
</h:body>
</html>
I tried to change CSS as suggested in some posts and tried to fire click event programmatically when user clicked once but all of that didn't help!
Your suggestions are welcomed.
Primefaces version: 5.3

Primefaces 5 overlayPanel broken after update

Today I discovered a new bug in P5. When I update the button which the overlay panel is referring to, it doesn't work anymore - The overlaypanel is not shown anymore.
As a workaround I do use PF('widgetVar').loadContents(); but this feels very uncomfortable.
In PF4 this did work without any workarounds.
Anyone got some solution?
My solution:
don't update single button that opens overlay, update both
also add dismissable="false" showCloseIcon="true"
in the case you are using overlay on a dialog: add appendTo="#(body)"
Example code:
<p:commandButton value="updateSection" update=":form:overlayPanelGroup" />
<h:panelGroup id="overlayPanelGroup">
<p:commandButton id="openOverlayBtn" process="#this" value="openOverlay"/>
<p:overlayPanel for="openOverlayBtn" showEffect="fade" hideEffect="fade" dismissable="false" showCloseIcon="true" appendTo="#(body)">
<h:outputText value="textSample"/>
</p:overlayPanel>
</h:panelGroup>
I don't know exactly what you are pointing at. What do you mean with updating the button?
For me the following code works fine with PrimeFaces 5.0:
<!DOCTYPE html>
<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:p="http://primefaces.org/ui"
xmlns:pm="http://primefaces.org/mobile">
<h:head>
</h:head>
<h:body>
<p:commandButton id="menuButton" value="Menu" icon="ui-icon-home"/>
<p:overlayPanel for="menuButton" widgetVar="menuPanel" at="left" showEffect="push">
<!-- overlayPanel content goes here -->
</p:overlayPanel>
</h:body>
</html>
Does this help you with your problem?

Dynamic tab content in primefaces using ui:include not working

I'm unable to use ui:include in tabView. I'm trying to make dynamic tabs using included Facelet.
Here's my code:
<p:tabView id="panelGl" var="tabContent" value="#{mainPageBackingBean.tabs}" widgetVar="panelGlJs" style="height: 100%;" dynamic="true" >
<p:ajax event="tabClose" listener="#{mainPageController.onTabClose}" oncomplete="questionDialogWV.show()" update="#(this) :questionForm:questionFormPanel" />
<p:ajax event="tabChange" onstart="setActive()" update="#(this)" />
<p:tab title="#{tabContent.title}" titletip="#{tabContent.description}" closable="true">
<ui:include src="#{mainPageBackingBean.tabContents}" />
</p:tab>
</p:tabView>
And #{mainPageBackingBean.tabContents} runtime value is pointing at this Facelet:
<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:p="http://primefaces.org/ui">
<p:panel>
<h:form>
<p:commandButton id="testEmail" value="" process="#this" actionListener="#{communicationChannelsController.testEmailChannel()}"/>
</h:form>
</p:panel>
</ui:composition>
When I use the above ui:include outside of p:tabView it works normally (I am able to invoke communicationChannelsController.testEmailChannel() without a problem). Also when I copy the contents of above file inside p:tab everything works fine also.
Problem is that, when combined p:tab and ui:include do not work, this bean method is not called.
What is the best approach at creating dynamic tabs using some navigation bean like mainPageBackingBean in my example?

primefaces facelets layout render blank page

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.

FaceletContext.includeFacelet trouble

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);

Resources