Change tab on button click without update tabView - jsf

I want to change a tab by clicking in commandButton. I'm controlling activeIndex on my bean and doing an update on tabView component. Everything works fine.
My problem is that I want to change the activeIndex without need doing an update on tabView, because update of that component is a bit slow.
Is it possible to change a tab by clicking on button, and do that without update?
Here is my actual code.
TabView component
<p:tabView id="tvFoo" dynamic="true" activeIndex="#{fooBean.activeIndex}">
<p:tab title="Title" id="someTab">
<ui:include src="someTabName.xhtml" />
</p:tab>
<p:tab title="Title2" id="anotherTab">
<ui:include src="anotherTabName.xhtml" />
</p:tab>
</tabView>
inside someTabName.xhtml
<p:commandButton value="go to anotherTab" actionListener="#{fooBean.tabChange('anotherTabName')}" />
fooBean, that controls tabs change
public void tabChange(String tabId) {
switch (tabId) {
case "anotherTabName":
activeIndex = 2;
RequestContext.getCurrentInstance().update("tvFoo"); //here is the line that I don't want to call
break;
}
Can I remove that line, RequestContext.getCurrentInstance().update("tvFoo");? Of course, if simply remove, the tab is not changed.
To resume, basically I want change the opened tab. I think that I can achieve this calling the changeTab event manually, but I don't know how do that.

Why don't you do an update on the tabview component by your command button?
I think you have to do an update somewhere, otherwise, how should the tabview notice the change? Moreover, as far as I know, the update function isn't slow at all.
To get the current index of the tabview you could play with the Faces Context:
TabView tabView = FacesContext.getCurrentInstance().getViewRoot().findComponent(aComponentId);
On tabView you can get and set the active tab individually.
I hope this helps, good luck!

Have you tried using the wizard component? I believe the behaviour you're looking for is similar to this primefaces wizard.
http://www.primefaces.org/showcase/ui/panel/wizard.xhtml

Related

Close dialog prior to navigate away from the page

PrimeFaces: 7.0
JSF: 2.2.13
JBoss: 7.1
Java: 1.8
Chrome: 83.0.4103.116
I have a simple confirmation dialog to go to another page, there a reason for the action should be provided as a text.
It boils down to the following lines of code:
<p:dialog id="dlg" widgetVar="dlg" modal="true">
<h:form id="dlgForm">
<p:inputText id="reason" required="true" value="#{bean.reason}"/>
<p:message for="reason"/>
<p:commandButton id="proceed" value="Proceed" update="dlgForm" action="#{bean.action}"/>
<p:commandButton id="cancel" value="Cancel" resetValues="true" onclick="PF('dlg').hide()">
<p:ajax update="dlgForm" resetValues="true"/>
</p:commandButton>
</h:form>
</p:dialog>
And the bean:
#ManagedBean(name = "bean")
#SessionScoped
class Bean {
public String processGrundFuerExportDlg() {
PrimeFaces.current().executeScript("PF('dlg').hide()");
return "other_page";
}
}
My requirements:
Dialog opens with the empty 'reason'-inputText.
If 'cancel' is pressed: dialog should close
If 'proceed' is pressed:
If reason is not empty: close dialog and navigate to the 'other_page'
If return is empty: show the error message and don't close the dialog
My problem with this code: the line
PrimeFaces.current().executeScript("PF('dlg').hide()");
seems to be executed AFTER the current page being left resulting in 'dlg' not being found (JavaScript error).
The not properly closed dialog produces a nasty side effect: After returning to my first page later on, the dialog overlay stays active and inputText elements can't be activated with the mouse (TAB works). Overlay logic in the event loop blocks mouse clicks to from being passed to the components on the page.
My question:
How this standard scenario should be properly implemented with JSF and PrimeFaces?
If Upgrade to other versions is required, are there some workaround for removing stale overlays without upgrading?
Disclaimer: I studied many related questions on StackOverflow and tried all proposed solutions without success. For example this one: Keep p:dialog open when a validation error occurs after submit
You won't be having this problem if you would redirect to the new page instead of triggering an Ajax update.
You can simply add ?faces-redirect=true to your returned string, so:
return "other_page?faces-redirect=true";
Or, if you are using faces-config, add <redirect/> to the <navigation-case>.
Then you can remove the script from your bean where you try to close the dialog.
See also:
How to navigate in JSF? How to make URL reflect current page (and not previous one)
If 'proceed' is pressed:
If reason is not empty: close dialog and navigate to the 'other_page'
If return is empty: show the error message and don't close the dialog.
All this above is handled with required true on reason inputText. If reason is empty action in proceed commandButton won't start.
You don' need to close your dialog before you are navigating to other page.

Re-Render PrimeFaces elements after certain events

I want to conditionally render my menuitem depending on which element I invoke my menu on.
Only problem is: The menuitem renders the moment the xhtml is loaded. Because of that, I'll only get "null" for my selected element.
Of course I can catch that by saying "if it`s null, just render it", but the real problem is that, once rendered, the menuitem stays rendered.
Is there any way to render/re-render my menuitem right AFTER I open the menu(by then I'll have the information needed)?
I've tried several ways to aquire this:
remoteCommand (I don't need to invoke any bean, so it seems to be the wrong tool)
PageReload(Will obviously close my menue)
Ajax(Might work, but I just started learning it -> In this case it did nothing)
EDIT:
Ajax does work. I've updated the code. Right now im re-rendering the contextMenue once I've selected an item, so the children will call their respective beans again and render correctly.
Only flaw is:
This takes for to long (guess this would lead to another question...)
I don't want to re-render the menue, but the children! If I re-render the children directly, ajax can't find them by id anymore, so it will crash.
Any ideas?
test.xhtml
<p:contextMenu for="treeId" ajax="false" id="openSP">
<p:menuitem value="Example" ajax="false"
action="#{MyClass.method}"
rendered="#{MyClass2.renderItem}" >
</p:menuitem>
</p:contextMenu>
<p:treeTable id="test"
...
<f:ajax event="select" render="openSP" />
...
</p:treeTable>

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.

Creating master child concent in primefaces

I'm using Primefaces 3.5 + MOJARA 2.2.
I'm trying to create a Master child kind of environment where we have all applications listed in one Tab with command buttons. Each command button will open up another tab in the same parent window.
To achieve this i'm using dynamic tabs with iframe
<p:tabView value="#{bean.tabs} var="tab">
<p:tab title="#{tab.title}" closable="#{tab.closable}">
<iframe src="#{tab.content}" class="ui-widget" width="100%" height="900px"/>
</p:tab>
</p:tabView>
Here tabs is a List and Tab is a POJO.
class Tab{
private String title;
private String content;//URL
private boolean closable;
//GETTER SETTERS
}
in Backing bean i create a Tab where in show command buttons as below.
public class Bean{
private List<Tab> tabs;
...
public Bean(){
tabs = new ArrayList<Tab>();
Tab tab1 = new Tab("Applicaton","dispApplications.xhtml",false);
tabs.add ( tab1 );
}
}
dispApplications.xhtml
<h:form id="buttonForm">
<h:panelGrid columns="6" border="0">
<c:forEach var="dataItem" items="${bean.applications}">
<h:column>
<p:graphicImage value="/images/#{dataItem.icon}"/>
<p:commandButton binding="#{bean.cmdButton}"/>
</h:column>
</c:forEach>
</h:panelGrid>
</h:form>
Problems:
I'm able to show initial "Applications" Tab. However when i try to invoke each application i had to force reloading of the entire page to get the tabs loaded. This i'm doing cmdButton.setOnClick("parent.location.href = parent.location.href") for each commandButton which is bound to Bean.
I also created an inline processListener for cmdButton which creates an instance of "Tab" and adds it to tabs.
I want to avoid complete page reloading to show tabs.
I want to highlight the new tab that is added/opened recently..
Tabclose is always closing first tab no matter which tab i try closing. Online primefaces showcase shows very clean implementation but i guess this works in 4.0 and hopefully this is a bug in 3.5 version.
This link from Baluc
has provided lot of help, but this is based on tabChange event and also the update is done using requestContext. This is not working when i use iframe.
Any other approach is also welcome.
Thanks in advance

Setting bean property before opening Primefaces dialog

I would like to achieve this functionality.
<p:column>
<p:commandLink value="prihlasit" oncomplete="dlg.show();"
action="#{signForProjectBean.setProjectForDetail(item)}" />
</p:column>
I think is pretty clear what I am trying to do, I would like to display detail of the row in dataTable on which user have clicked. So my approach is to set property of current row to bean and then show the detail in dialog. But it is not working and I am feeling that I am doing something really wrong:-)
If the dialog component is supposed to display the selected item, then you need to ajax-udpate the dialog's content before opening it. Otherwise it will still display the old content as it was when the page is rendered for the first time.
<p:commandLink value="prihlasit" update=":dlg" oncomplete="dlg.show();"
action="#{signForProjectBean.setProjectForDetail(item)}" />
...
<p:dialog id="dlg" ...>

Resources