Tab is displaying the default , Need to show the tab which we select - jsf

I am using prime face version 3.4 , The problem is with the tab view display.
<p:messages id="messages"/>
<p:tabView id="tabView" dynamic="false">
<p:tab id="tab1" title="Navigation">
<p:tab id="tab2" title="Email Address">
<p:tab id="tab3" title="Password">
</p:tabView>
It's a Tabbed page with 3 Tabs(Notification , Email and Password) , If am on Email tab without entering any values i click submit , it displays the error message at the top and default to the first tab , I need to show the Email Tab

With ajax=false, the whole page gets refreshed after you click the button and tab view takes you to the first page just as if you were navigating to that page for the first time.
You could either set Ajax to true or use an integer on your bean as the selected index for the tabview (there's a property called selectedIndex on the tabview if memory doesn't fail me). The second option, however, would only work for view, session and application scoped beans.

Place the <p:messages id="messages"> tag inside the <p:tab id="tab2" title="Email Address"> tag. Note that it will display messages from any validated component inside the same form (or from any of your tabs). You should use <p:message for="componentId"> to show component-specific messages.

Related

defer loading of an output panel within a tab managed by primefaces tabview tag

Presentation
I am facing an issue to get an output panel load in deferred mode when the panel is included in a tab managed by Primefaces.
Here is a code sample:
<p:tabview value="#{b.tabs}" var="tab" dynamic="true" cache="false">
<p:tab title="#{tab.name}">
<p:outputpanel id="reportsDisplayId" >
<p:outputPanel id="reportsPanel" deferred="true" >
<h:outputText id="reports" escape="false" value="#{tab.report}" />
</p:outputPanel>
</p:outputpanel>
</p:tab>
</p:tabView>
"tab.report" is generated by Jasper. Generating this report takes time in most cases. This is the reason for using the deferred mode.
Tabs are managed using p:tabView in dynamic mode and no caching, so that tabs are refetched from the server at each tab change.
This works fine for the first tab: the display of the panel is effectively deferred without preventing the context from being displayed. Upon switching between tabs, the whole content of the tab is displayed only when the report is ready.
I have tried using deferredMode="visible", but this feature seems to intended for scroll visibility. I have tried enclosing the h:form into a p:outputPanel and updating the panel instead of the form.
Without success so far.
Working with p:RemoteCommand
I have progressed using p:RemoteCommand and found that others have been following that path, however with some difficulties. I will post my progress.
Here are related posts:
p:remote command not working in asynchronous mode
The bug reported here seems to have disappeared
JSF 2.1
Wildfly 8.2.1.Final
Primefaces 8.0.3
Omnifaces 2.7.7
Java 8
Here is a solution which relies on p:remoteCommand and not on the deferred attribute of output panel.
<h:form id="boardForm">
<p:tabview id="boardTabs" value="#{b.tabs}" var="tab" dynamic="true" cache="false">
<p:ajax event="tabChange" listener="#{board.onTabChange}"/>
<p:tab title="#{tab.name}">
<!-- First rendering: display a loading gif -->
<p:graphicImage value="/resources/img/loading.gif"
rendered="#{!board.loading}" alt="loading" />
<!-- Second rendering: display the report itself -->
<p:outputPanel id="reportsPanel" rendered="#{board.loading}" >
<h:outputText id="reports" escape="false" value="#{board.getJasper(tab)}"/>
</p:outputPanel>
<p:remoteCommand name="deferredLoader_#{board.tabIdx}" async="true" autoRun="true"
actionListener="#{board.setLoading(true)}" rendered="#{!board.loading}"
update=":boardForm:boardTabs:#{board.tabIdx}:jspReportDisplay" />
</p:tab>
</p:tabView>
</h:form>
The rendering goes in two phases:
A simple gif is displayed.
The whole report is displayed. However, the gif
is displayed as long as the report is not ready.
Detailed comments:
Upon tab switch, the event "tabChange" invokes the bean method "onTabChange", which sets "loading" to false and records the active tab index.
As "loading" is false, the gif is displayed, the report is not displayed, and the remote command is run.
The remote command is async so that it is possible to switch to another tab before the active tab is fully displayed.
The remote command sets back "loading" to false before updating the tab for the second phase, so that: (1) the gif is not displayed again; (2) the report is now generated; (3) the auto-run remoteCommand is not run infinitely many times.
the name of remoteCommand is indexed to the active tab to ensure unicity of names for each remoteCommand in various tabs.
Well, I guess there are more elegant solutions than this one. This is the one I found.

How to get all Tabs without going into onTabChange

I want to know how to get all the tabs in the JSF layer without going into the ontabChange method.
I have a system with dynamic tabs. Depending on the values users keyed in, different tabs will be rendered. After saving, the user needs to be directed to the "Account" tab, however with all the tab renderings, the index for "Account" may have changed.
If user do a tab change then it's fine, because I can get all the children for the tab and navigate to whichever index "Account" is.
But the problem is, how do I populate the tab and the children if the user did not call the ontabchange method, meaning that the user did not do any navigate to other tabs and straight away save the information.
<p:tabView id="tabView"
activeIndex="#{userBacking.tabInt}">
<p:ajax event="tabChange" immediate="true" update=":form:message"
listener="#{userBacking.onTabChange}" />
<p:tab id="tab1" title="Personal Information">
// Items for tab 1
</p:tab>
<p:tab id="tab2" rendered="#{userBacking.renderedTab2}
title="Education">
// Items for tab 2
</p:tab>
<p:tab id="tab3" rendered="#{userBacking.renderedTab3}"
title="Qualifications">
// Items for tab 3
</p:tab>
<p:tab id="tab4" rendered="#{userBacking.renderedTab4}"
title="Contact Information">
// Items for tab 4
</p:tab>
<p:tab id="tab5" title="Account">
// Items for tab 5
</p:tab>
</p:tabView>
Without the user calling the ontabchange, I want to get all the tabs available and navigate to the "Account" tab.

Primefaces Wizard doesn't execute onclick method call

I try to build a form where a user can enter data step by step. After trying a FlowScoped solution I now try to implement the Primefaces wizard.
Description:
My main.xhtml:
<h:form id="antragErfassenForm">
<p:wizard showStepStatus="false" widgetVar="wiz" showNavBar="false" >
<p:tab id="basic_decision_tab" title="Grundsatzentscheidungen">
<ui:include src="/eAkte/basic_decisions.xhtml" />
</p:tab>
<p:tab id="driving_ways_tab" title="Fahrtwegvarianten">
<ui:include src="/eAkte/driving_ways.xhtml" />
</p:tab>
</p:wizard>
</h:form>
Inside the include files I have buttons to navigate between the tabs.
The next button in the first tab 'basic_decisions.xhtml':
<p:commandLink value="Next" onclick="#{eAkteController.callDrivingWays()}; PF('wiz').next();" />
Depending on the result from callDrivingWays() (which evaluates the data of the first tab) the second tab has a different content.
My problem:
The method callDrivingWays() isn't called when clicking the next button on the first tab. Instead it is already called when the first tab is loaded. That's why I always have an empty second page.
I tried switching the method call callDrivingWays() inside an actionListener inside the button or the flowListener of the Wizard. After that the method is called at the correct time, but when clicking on the next button I get an exception, that my component ID has already been used before.
Does anyone has any suggestions?
Try using the flowListener attribute of p:wizard
<p:wizard flowListener="#{yourBB.yourMethod}" nextLabel="Next" backLabel="Back" showNavBar="false" widgetVar="myWizard">
In your backing bean code instead you can implement the actionListener like this:
public String yourMethod(FlowEvent event) {
if(event.getOldStep().equals("driving_ways_tab")){}
if(event.getNewStep().equals("driving_ways_tab")){}
you need getOldStep and getNewStep to perform some changes according to the tab you are entering, exiting.

PrimeFaces wizard - how can I use onstart/oncomplete for tab change ajax loading

I'm using PrimeFaces 4.
I don't want to use p:ajaxStatus because I only want to show loading for a few components.
So I have a p:blockUI component that I usually show during ajax events by doing this:
onstart="loading.show();" oncomplete="loading.hide();"
But for p:wizard component I don't know how can I do that when the user change tabs (clicking next/back buttons or clicking in the tab title). I tried the following inside the wizard:
<p:wizard id="wizard" flowListener="#{myBean.onFlowProcess}" style="display: inline-block;" backLabel="Prev" nextLabel="Next" showNavBar="true" widgetVar="wizardWV">
<p:ajax event="tabChange" onstart="loading.show();" oncomplete="loading.hide();" />
<p:tab id="tab1" title="My tab 1">
<p:panel>
<h:outputLabel value="test" />
</p:panel>
</p:tab>
<p:tab id="tab2" title="My tab 2">
<p:panel>
<h:outputLabel value="test2" />
</p:panel>
</p:tab>
</p:wizard>
Then I got the error:
<p:ajax> Unable to attach <p:ajax> to non-ClientBehaviorHolder parent
Is there any way I could achieve this?
Thanks
That's is because the wizard isn't a client behavior container.
The standard flow of a wizard is the tabs are just for display purposes in the heading. You should be using the Next/Back triggers for the wizard flow.
Refer to : http://www.primefaces.org/showcase/ui/panel/wizard.xhtml
Has the basic features/flow, but some more links
http://www.primefaces.org/docs/vdl/3.5/primefaces-p/wizard.html
If you're trying to make your tabs clickable then that's a different story, you'll need to setup your flow listener, have them all select the same method/action as the next - but pass a param to the backing bean and manually determine the flow. You could setup a remote call in PF with an onclick attached to access your intent of the waiting on load.
I would look at use case scenarios, maybe Wizard is the wrong component you're looking for?
Looking at the code provided, you're tabs currently are not clickable, and I cannot see your back/next action buttons.

Primefaces commandButton action attribute not being called

I am creating a JSF application with primefaces. Basically I have this view. There is a tab view which for each tab contains a command button and a accordion panel (another kind of tab view). The tabs of the accordion panel among other elements, contain each one command button. My problem is that the first command button (under 1 level of tabs) calls correctly the action method when it is clicked, while the second button (under 2 level of tabs) does not. I should say that both the tabView and accordionPanel are working correctly, since they are displaying the information they should display.
I am posting a simplified version of my view so that you can see what is happening.
<h:form>
<p:tabView id="unitTabs" orientation="left" dynamic="true" cache="false" var="unit" value="#{unitController.getUnitsOfLoggedInUser(loginController.checkedUser)}">
<p:tab id="unitTab" title="#{unit.unitName}">
<p:commandButton value="Add Lecture" action="#{unitController.setTemporary(unit)}" onclick="createLectureDialog.show()">
<p:accordionPanel id="lectureTabs" value ="#{lectureController.getLecturesForUnit(unit)}" var="lecture" dynamic="true" cache="false">
<p:tab title="#{lecture.lectureName}">
<p:commandButton value="Add Criterion" action ="#{lectureController.setTemporary(lecture)}" onclick="createCriterionDialog.show()" >
</p:tab>
</p:accordionPanel>
</p:tab>
</p:tabView>
</h:form>
What am i doing wrong? Thanks
This construct requires that the EL expression in the value attribute of the <p:tabView> and <p:accordionPanel> returns exactly the same value during processing the form submit as it was during the initial display.
If the bean is request scoped and/or the value depends behind the scenes on a request based parameter or variable and it thus returns a different value on every request, then it will fail because JSF cannot locate the button which was been invoked. To fix it, the bean needs to be placed in the view scope and the getter method should not contain any business logic, or any request based parameters or variables should be retained in the subsequent requests.
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated - point 4.

Resources