When update an accordion It doesn't hold the open/closed tab - html

I have a big problem with Primefaces accordion.
I have an outputPanel with an header and an accordion with 2 tabs.
If I close the first tab and change a field in the second tab, it open the first tab and close the second. How can I keep the status of the tabs?
This is a simple example:
<p:outputPanel id="content">
<p:outputPanel id="header" />
<p:accordionPanel multiple="true">
<p:tab title="firstTab">
<p:panel>
<p:inputText id="firstInput" value="firstInput">
<p:ajax event="change" update="content" />
</p:inputText>
</p:panel>
</p:tab>
<p:tab title="secondTab">
<p:panel>
<p:inputText id="secondInput" value="secondInput">
<p:ajax event="change" update="content" />
</p:inputText>
</p:panel>
</p:tab>
</p:accordionPanel>
</p:outputPanel>
How can i resolve it? Any suggestion?

AccordionPanel has an attribute called activeIndex, you could set this attribute from your MB so it doesn´t change after an update. See for instance https://www.primefaces.org/docs/vdl/6.1/core/primefaces-p/accordionPanel.html

Based on cagatay civici's answer provided in the link by #Christian I created a simple example, because it was not working out of the box for me.
The example.xthml:
<h:form styleClass="accordionForm">
<p:accordionPanel multiple="true"
activeIndex="#{sessionBean.activeTabs}">
<p:ajax event="tabChange" />
<p:ajax event="tabClose" />
<p:tab title="Tab1">
<p:panel>
<p:inputText id="firstInput" value="firstInput">
<p:ajax event="change" update="#(.accordionForm)" />
</p:inputText>
</p:panel>
</p:tab>
<p:tab title="Tab2">
<p:panel>
<p:inputText id="secondInput" value="secondInput">
<p:ajax event="change" update="#(.accordionForm)" />
</p:inputText>
</p:panel>
</p:tab>
</p:accordionPanel>
</h:form>
The sessionBean.java:
#Named("sessionBean")
#SessionScoped
public class SessionBean implements Serializable {
private static final long serialVersionUID = 1L;
private String activeTabs = "";
public String getActiveTabs() {
return activeTabs;
}
public void setActiveTabs(String activeTabs) {
this.activeTabs = activeTabs;
}
}
Explanation:
The two p:ajax tags trigger a POST request if a tab is either opened ("tabChange") or closed ("tabClosed"), since this is the default action for the accordionPanel. Hence, I wrapped the p:accordionPanel with an h:form. If you inspect your network traffic you can see how the list of active tabs is sent to the server.
Bear in mind that I update the surrounding form instead of the accordionPanel itself. Therefore, I use Primefaces Selectors.

Related

Primefaces: Update not working for two components in different tabs

I have two selectBooleanCheckbox in differet tabs that are linked to the same variable in the backend bean, like this:
.xhtml:
<p:tabView id="tabsView" widgetVar="tabPanelWidget" dynamic="true" cache="true">
....
<p:tab id="tab1">
<p:outputPanel id="panel1">
<p:fieldset toggleable="false">
<p:panelGrid id="panelGrid1">
<p:row>
<p:column>
<p:outputLabel for="toggle1"/>
<p:selectBooleanCheckbox id="toggle1" value="#{backingBean.toogleBool}">
<p:ajax update="#(.toggle2)"/>
</p:selectBooleanCheckbox>
<p:column>
</p:row>
</p:panelGrid>
</p:fieldset>
</p:outputPanel>
</p:tab>
....
<p:tab id="tab2">
<p:outputPanel id="panel2">
<p:fieldset toggleable="false">
<p:panelGrid id="panelGrid2">
<p:row>
<p:column>
<p:outputLabel for="toggle2"/>
<p:selectBooleanCheckbox id="toggle2" value="#{backingBean.toogleBool}">
<p:ajax update="#(.toggle1)"/>
</p:selectBooleanCheckbox>
<p:column>
</p:row>
</p:panelGrid>
</p:fieldset>
</p:outputPanel>
</p:tab>
</p:tabView>
backingBean.java :
....
#Getter #Setter private boolean toggleMailAnhangExtrahieren = true;
....
Obviously this isn't my whole code as that would be too much to post here but I hope I included everything relevant. As you can see I try to use ajax to update the other selectBooleanCheckbox when one of them is clicked. As they are bound to the same variable, I would expect both selectBooleanCheckboxes to have the same status (both checked or both unchecked), but the other checkbox does not update. What am I doing wrong?
You need to fix the update part in the p:ajax tags:
#(.<class>) is a class-selector (Primefaces is using the jQuery Selector API, see https://api.jquery.com/category/selectors/), but you want to reference an id. So just use the id itself in the p:ajax tag, e.g.
<p:ajax update="toggle2"/>
Try using the tab id like this:
<p:ajax update="#form:tabsView:toggle2"/>

Primefaces SelectOneMenu reselect option in deleted row within DataTable in new row

I have a selectonemenu within a datatable column. The selected options are messed up when I delete a row and it doesn't seems to reflect the value in the backend bean. For example, I selected Item A in the first row, then add another row and select Item B in the second row, then when I delete the first row, the second row is move up with Item A selected, but the backend value of second row is still Item B and Item A is removed from the collection.
<p:dataTable id="insertDetailTable" styleClass="data-table"
rowIndexVar="rowIndex" var="receivingDetail"
value="#{receivingController.receiving.receivingDetails}">
<p:column headerText="Item">
<p:selectOneMenu styleClass="input" id="item"
value="#{receivingDetail.item}" required="true"
requiredMessage="Item is required" converter="itemConverter">
<f:selectItem itemLabel="Select an item" itemValue="#{null}"
noSelectionOption="true" />
<f:selectItems value="#{receivingController.items}" var="item"
itemLabel="#{item.code} - #{item.name}" itemValue="#{item}" />
<p:ajax update="insertDetailTable" />
</p:selectOneMenu>
</p:column>
<p:column styleClass="action-cell">
<f:facet name="header">
<p:commandButton icon="ui-icon-plus" value="Add"
action="#{receivingController.insertDetail('insert')}"
immediate="true" />
</f:facet>
<p:commandButton icon="ui-icon-trash"
action="#{receivingController.deleteDetail('insert', receivingDetail)}"
immediate="true">
<p:confirm header="Confirmation"
message="Do you wish to remove the selected detail?"
icon="ui-icon-alert" />
</p:commandButton>
</p:column>
</p:dataTable>
The backend code of adding a new row and deleting a row:
public void insertDetail(String owner) {
ReceivingDetail receivingDetail = new ReceivingDetail();
receivingDetail.setReceiving(receiving);
receivingDetail.setQtyStored(new BigDecimal("0.00"));
receiving.getReceivingDetails().add(receivingDetail);
RequestContext context = RequestContext.getCurrentInstance();
if (owner.equals(OWNER_INSERT)) {
context.update("insertForm");
context.execute("PF('insertDialogWV').show();");
} else if (owner.equals(OWNER_UPDATE)) {
context.update("updateForm");
context.execute("PF('updateDialogWV').show();");
}
}
public void deleteDetail(String owner, ReceivingDetail receivingDetail) {
receiving.getReceivingDetails().remove(receivingDetail);
ItemService itemSvc = (ItemService) getService(ItemService.class);
setItems(itemSvc.find());
RequestContext context = RequestContext.getCurrentInstance();
if (owner.equals(OWNER_INSERT)) {
context.update("insertForm");
context.execute("PF('insertDialogWV').show();");
} else if (owner.equals(OWNER_UPDATE)) {
context.update("updateForm");
context.execute("PF('updateDialogWV').show();");
}
}
Any idea what went wrong with my code?
I am using Primefaces 5 and JSF 2.2.
This is the first time I posting a question, not sure did I do it right, let me know if I need to correct anything, thanks in advance.
Edited:
Just in case this information is required, the datatable resides within a dialog as such.
<h:form id="insertForm">
<p:dialog id="insertDialog" widgetVar="insertDialogWV" modal="true"
draggable="false" resizable="false" header="Add Record"
closable="false">
</p:dialog>
</h:form>
Removed immediate="true" in the command button and it works, the table select and show the value according to the backend bean properly.

How to update value in p:dialog and display in the p:dialog

I have a datatable, and at the last column I will have an edit action, it will trigger the dialog box. However, I found the value in the dialog box is not updated. Can anybody to help on this?
My code as below. In fact the bean.currentItem.name and bean.currentItem.age should base on my selection from the table. I check the bean.currentItem is not null and is refer to my selection from preEdit method, but the value never show up in p:dialog.
<p:dataTable ....>
<p:column...
<p:column...
<p:column>
<f:facet name="header">
<h:outputLabel value="Update" />
</f:facet>
<p:remoteCommand name="preEdit" action="#{bean.preEdit}"
process="#this" update="#this #form:dlg">
<f:setPropertyActionListener target="#{bean.currentItem}"
value="#{thisItem}" />
</p:remoteCommand>
<p:commandLink styleClass="no-decor"
oncomplete="preEdit();PF('dlg').show();" value="Edit"/>
</p:column>
</p:dataTable>
<p:dialog header="#{lbl.tt_cat_upd}" widgetVar="dlg" id="dlg"
resizable="false" >
<h:outputLabel value="#{bean.currentItem.name}" />
<h:outputLabel value="#{bean.currentItem.age}" />
</p:dialog>
How about removing your p:remoteCommand and let your p:commandLink do all the work for you?
Assuming you have a h:form surrounding both your dataTable and your dialog
<p:commandLink action="#{bean.preEdit}" process="#this" update="dlg" styleClass="no-decor" oncomplete="PF('dlg').show()" value="Edit">
<f:setPropertyActionListener target="#{bean.currentItem}"
value="#{thisItem}" />
</p:commandLink>
If your dataTable is not in the same form with your dialog, you might replace update="dlg" by update=":formIdContainingDialog:dlg"

How to Update outputpanel from commandbutton which is inside the datatable using primefaces

Commandbutton with id("myButtonId2") works fine. I mean it updates "myOutputPanel"
but commandbutton(myButtonId) which is inside datatable doesn't update outputPanel. I found the suggestions and tried with the following,
update=":myForm:myOutputPanel"
update="#myForm"
update=":myOutputPanel"
But none of them worked...
Here is the snippet...
<h:form id="myForm" prependId="false">
<p:panel id="myPanel">
<p:dataTable id="myDatatable">
<p:column style="width:4%">
<p:commandButton id="myButtonId" actionListener="#{bean.showPanel}" update="myOutputPanel"/>
</p:column>
</p:dataTable>
<p:commandButton id="myButtonId2" update="myOutputPanel"/>
</p:panel>
<p:outputPanel id="myOutputPanel" rendered="#{bean.show}">
//some stuff
</p:outputPanel>
Try to put your <p:outputPanel /> inside a <p:panel />
and add a "widgetVar" attribute
For example : <p:panel widgetVar="var" [..]>
and just update the panel directly with update="#widgetVar(var)"

Wizard doesn't go to next step

I have p:wizard inside a dialog. When I click on the next button, nothing happens. I've even put h:messages to catch any validation problems. But nothing appears. Here's my code:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<cc:interface>
<cc:attribute name="actionNewComplete" required="false"/>
<cc:attribute name="update" required="false"/>
</cc:interface>
<cc:implementation>
<h:form prependId="false" id="formCreateOffre">
<h:messages showDetail="true"/>
<p:wizard id="wizardOffre" widgetVar="widgetWizardOffre" showNavBar="false" flowListener="#{offreController.handleFlow}">
<p:tab id="tabOffre" title="Offre">
<p:panelGrid styleClass="ui-net-table">
<p:row>
<p:column>
<p:outputLabel value="#{bundle.CreateOffreLabel_participant}" for="participant" />
<p:inputText styleClass="text" style="width: 50px;" id="participant" value="#{offreController.selected.participant}" title="#{bundle.CreateOffreTitle_participant}" />
</p:column>
</p:row>
<p:row>
<p:column>
<p:outputLabel value="#{bundle.CreateOffreLabel_rendezvous}" for="rendezvous" />
<p:calendar styleClass="text" id="rendezvous" value="#{offreController.selected.rendezvous}" disabled="#{offreController.selected.realisation eq null}" title="#{bundle.CreateOffreTitle_rendezvous}">
<p:ajax event="dateSelect" update="delais"/>
</p:calendar>
</p:column>
</p:row>
</p:panelGrid>
</p:tab>
<p:tab id="tabOffreClient" title="Client">
clients
</p:tab>
<p:tab id="tabOffreActivite" title="Activité">
activités
</p:tab>
<p:tab id="tabOffreService" title="Service">
services
</p:tab>
</p:wizard>
<p:commandButton value="Précédent" onclick="widgetWizardOffre.back();" icon="ui-icon-seek-prev"/>
<p:commandButton value="Suivant" onclick="widgetWizardOffre.next();" icon="ui-icon-seek-next" iconPos="right"/>
</h:form>
</cc:implementation>
</html>
Here is the code of the bean.
#ManagedBean(name = "offreController")
#SessionScoped
public class OffreController extends AbstractController<Offre> {
#ManagedProperty(value = "#{navigationController}")
private NavigationController navigation;
#EJB
private app.tfe.netescape.business.OffreFacade ejbFacade;
public OffreController() {
}
public String handleFlow(FlowEvent event) {
return event.getNewStep();
}
The flowListener method is called and returns the next step but nothing happens.
Make sure you have a getter and setter for every bean property you reference in your code. PrimeFaces will fail ungracefully on the wizard step in exactly this manner if it is unable to find both a getter and a setter - even for properties which you are only reading.
Addendum: also, the getters and setters should only do a get and a set of a local value. PrimeFaces doesn't handle other getters and setters well (I cannot explain why this doesn't work, but I've certainly observed it). If you have any additional logic, it should be processed in your listeners.
what version of primefaces did you use?
If is version 5.1 change the event onclick:
onclick="widgetWizardOffre.next();"
by --->
onclick="PF('widgetWizardOffre').next();"
and use same for the event back: onclick="PF('widgetWizardOffre').back();"
Your are already hiding the Navigation bar (next&back buttons), How can the navigation bar work then? Remove showNavBar="false", it's true by default .