JSF how to restrict validation to open accordion tab - validation

Each of my tabs has a data table, an input and an add button. When I click the add button the validation happens on open and closed tabs. I see the errors for the closed tabs in the open tab. Is there a way to make the validation only occur in the open tab.
<p:accordionPanel id="pnl_accord_codetables" dynamic="true" cache="false">
<p:ajax event="tabChange" listener="#{pc_Maintenence.onTabChange}" immediate="true"/>
<c:forEach items="#{pc_Maintenence.codeMaintenenceTables}" var="codetable">
<p:tab title="#{codetable.tableName}">
<util:datatable_util dataTableTemplate="#{codetable}"
dataTableList="#{pc_Maintenence.getDataTableList(codetable.tableList_managedBeanName.concat('.').concat(codetable.tableList_propertyName))}"
dataTableListItem="#{pc_Maintenence.getDataTableListItem(codetable.tableList_rowItemClassName, codetable)}"
actionMethodsBean="#{pc_Maintenence}"
buildMessagePanel="true"/>
</p:tab>
</c:forEach>
</p:accordionPanel>
This code is inside the composite
<p:panel id="pnl_add" rendered="#{cc.attrs.dataTableTemplate.addRow}">
<ui:repeat value="#{cc.attrs.dataTableTemplate.columns}" var="column">
<p:outputLabel styleClass="outputLabel" value="#{column.heading}"
for="inputtext" rendered="#{column.inputForAddingRecord}"/>
<p:inputText value="#{(cc.attrs.dataTableListItem)[column.name]}"
rendered="#{column.inputForAddingRecord}" id="inputtext"
required="#{not empty param[cc.add.clientId] and column.required}"
validator="#{column.validate}"/>
<div class="clear"> </div>
</ui:repeat>
</p:panel>
<p:panel id="pnl_commandbuttons">
<p:commandButton styleCl2ass="commandButton"
rendered="#{cc.attrs.dataTableTemplate.addRow}"
binding="#{cc.add}"
action="#{cc.attrs.actionMethodsBean.addRowAction(cc.attrs.dataTableTemplate)}"
value="Add"
update="pnl_datatable pnl_add pnl_msg #parent"
title="Add">
<p:collector value="#{cc.attrs.dataTableListItem}" addTo="#{cc.attrs.dataTableList}" />
</p:commandButton>
<p:commandButton styleClass="commandButton"
rendered="#{cc.attrs.dataTableTemplate.addRow or cc.attrs.dataTableTemplate.editable}"
action="#{cc.attrs.actionMethodsBean.submitAction(cc.attrs.dataTableTemplate)}"
value="Submit"
update="pnl_datatable pnl_add pnl_msg #parent"
title="Submit">
</p:commandButton>
</p:panel>
This is my validation method inside of my columns class
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
ResourceBundle resource = (ResourceBundle)getManagedBean("regex");
String pattern = resource.getString(this.regexName);
if(pattern != null){
RegexValidator regexValidator = new RegexValidator();
regexValidator.setPattern(pattern);
regexValidator.validate(context, component, value);
}
}

Related

jsf f:ajax tag corrupts request

Am using Spring with JSF
I have a view scoped bean which contains a function, the xhtml file contains a dropdown menu which on value change updates some message to the user and a button which calls the function. When I change the dropdown and click the button, the function is not called
Upon removing the tag
<f:ajax event="blur" render="type_message" />, the function is called and it worked fine
it same problem as in Primefaces Commandbutton not working after an update made by select box
#Scope("view")
#Component("propertyBean")
public class PropertyBean implements Serializable {
...
public String update() {
...
return"/page.xhtml";
}
}
xhtml
<h:selectOneMenu id="type" required="true"
requiredMessage="#{msgBean.getRequired()}"
styleClass="btn btn-white dropdown-toggle" style="width:100%"
value="#{propertyBean.property.propertyDetails.type}"
converter="#{typeConverter}">
<f:selectItem itemValue="#{null}" itemLabel="choose item"
noSelectionOption="true" />
<f:selectItems value="#{dataBean.availableTypes}"
var="typeObj" itemValue="#{typeObj}"
itemLabel="#{typeObj.type}"/>
<f:ajax event="blur" render="type_message" />
</h:selectOneMenu>
<h:message id="type_message" for="type"
infoClass="help-block" errorClass="help-block error" />
<h:commandButton id="update" value="save"
onclick="if( validate('submitForm')==true){ updateProperty();} else{ return false;}"
action="#{propertyBean.update}"
class="btn btn-green btn-lg arabic"
rendered="#{propertyBean.isNew == false}">
<f:param name="propertyId" value="#{propertyBean.property.id}">
</f:param>
</h:commandButton>
on changing <f:ajax> to <p:ajax> it worked, any explanations

How to AJAX update components in single tab of p:accordionPanel from outside?

I have a p:accordionPanel which represents a list of items and in each tab there is a form. Upon submitting any of the repeating forms, it is possible that extra data in needed, which is when a p:dialog is popped up prompting the user to enter some more data. That dialog is defined outside the accordion panel because, unlike the items from the accordion, only one of them can be showing at a time so there is no need to augment the HTML served by repeating it in each tab of the accordion.
The definition of the accordion looks as follows (simplified but with all the relevant descriptors):
<p:accordionPanel id="myAccordion" value="#{managedBean.getAccordionList}" var="item" multiple="false" dynamic="true" cache="true">
<p:ajax event="tabChange" listener="#{managedBean.processTabChange}"/>
<p:tab title="#{item.tabTitle}" id="itemTab">
<h:form id="itemForm">
<h:outputLabel for="itemName" value="Item Name:"/>
<p:inputText id="itemName" title="Item Name:"
maxlength="16" value="#{appeal.itemName}">
</p:inputText>
Consequently, the HTML rendered for itemName is myAccordion:0:itemForm:itemName in the first instance, myAccordion:1:itemForm:itemName in the second, etc.
The dialog is defined as follows:
<p:dialog id="commentDialogID" header="Enter comment" widgetVar="commentDialog" modal="true" resizable="true" height="auto">
<h:form id="commentForm">
<h:outputLabel for="comment" value="Comment:"/>
<p:inputTextarea id="comment" title="Comment"
rows="6" cols="33"
value="#{managedBean.activeItem.comment}"
required="true">
<f:ajax render="comment"/>
</p:inputTextarea>
<h:commandButton value="Submit" action="#{managedBean.proceed}" onclick="PF('commentDialog').hide();">
<f:ajax render="*** ??? ***"/>
</h:commandButton>
</h:form>
</p:dialog>
What I have repeatedly been failing at are attempts to f:ajax update only a single tab in the accordion panel, the active one from which the dialog was popped up. I tried using
:myAccordion:#{managedBean.activeItem.displayIndex}:itemForm:itemName
:myAccordion:#{managedBean.activeItem.displayIndex}:itemForm
:myAccordion:#{managedBean.activeItem.displayIndex}:itemTab
in place of *** ??? *** but none of them would compile:
javax.faces.FacesException: <f:ajax> contains an unknown id ':myAccordion:0:itemForm' - cannot locate it in the context of the component j_idt20
If I skip the index token (e.g. :myAccordion:itemForm:itemName) it does compile but it does functionally nothing. The Item entity class has a getDisplayIndex which does accurately return the index of the active tab.
My problem is quite similar to that which is described in this question, which doesn't really have a good answer. Could it be a limitation of PrimeFaces?
I don't know what version of Primefaces you are using, but this seems to be a bug in Primefaces 5.1.1 where i could recreate this issue. By upgrading to Primefaces 5.2, the ajax EL could suddenly find the referenced id. I can post a MCVE if needed.
Edit: The MCVE:
XHTML:
<h:form id="itemForm">
<p:accordionPanel id="myAccordion" binding="#{accordionView}" value="#{playgroundController.users}" dynamic="true" activeIndex="#{playgroundView.activeIndex}" var="user" multiple="false">
<p:ajax event="tabChange" update="commentDialogID"/>
<p:tab title="#{user.name}">
<h:outputLabel for="itemName" value="Item Name:" />
<p:inputText id="itemName" title="Item Name:" maxlength="16"
value="#{user.amount}">
</p:inputText>
<p:commandButton value="showDialog" onclick="PF('commentDialog').show();"></p:commandButton>
</p:tab>
</p:accordionPanel>
</h:form>
<p:dialog id="commentDialogID" header="Enter comment" widgetVar="commentDialog" modal="true" resizable="true" height="auto">
<h:form id="commentForm">
<h:outputLabel for="comment" value="Comment:"/>
<p:inputTextarea id="comment" title="Comment"
rows="6" cols="33"
value="#{playgroundView.activeIndex}"
required="true">
<f:ajax render="comment"/>
</p:inputTextarea>
<p:commandButton value="Submit" onclick="PF('commentDialog').hide();" update=":itemForm:myAccordion:#{playgroundView.activeIndex}:itemName" ></p:commandButton>
</h:form>
</p:dialog>
PlaygroundView Bean:
Note that in this example the activeIndex has to have an initial value, otherwise this EL:
update=":itemForm:myAccordion:#{playgroundView.activeIndex}:itemName"
will resolve wrongly and will throw an error that it cannot find the id of the referenced component. This of course has the drawback that the first tab will be open when the page loads, but that's another issue
private String activeIndex = "0";
public String getActiveIndex() {
return activeIndex;
}
public void setActiveIndex(String activeIndex) {
this.activeIndex = activeIndex;
}
PlaygroundController Bean:
private List<User> users;
#Override
public void initializeView() {
createUsers();
}
public void createUsers() {
User user1 = new User();
User user2 = new User();
User user3 = new User();
user1.setName("User123");
user1.setAmount(1);
user2.setName("User456");
user2.setAmount(2);
user3.setName("User12312345111111111111111111111111111");
user3.setAmount(3);
List<User> userList = new ArrayList<User>();
userList.add(user1);
userList.add(user2);
userList.add(user3);
users = userList;
}
User:
public class User implements Serializable {
String name;
int amount = 0;
}
You should update the commandButton on the tabChange event.
<p:ajax event="tabChange" listener="#{managedBean.processTabChange}" update=":commentForm:commandButtonId"/>
The render attribute <f:ajax> inside the <h:commandButton>is evaluated during the render phase and not sooner afaik. So if you do not update it, it will always point to '0'. Check the source in your browser developer tool and check your ajax requests (things you should always do for debugging). You will see the full clientId with the ':0:' and you will not see it changing on the ajax requests.

Open PrimeFaces Dialog located in another .xhtml file

I have a number of questions that are related to each other so the title of question may not be appropriate. Sorry for this.
I want to have a p:inputText and p:commandButton in a p:dialog such that when the user presses that button or presses enter key the value entered in the
p:inputText will be saved in the database. To do this I followed this example http://www.primefaces.org/showcase/ui/dialogForm.jsf and it worked fine when I tried it in a seperate .xhtml file in which there were no other dialogs or command buttons.
<h:body>
<h:form id="form">
<p:commandButton id="showDialogButton" type="button" value="Show" onclick="PF('dlg').show()" />
<p:dialog header="Enter FirstName" widgetVar="dlg" resizable="false">
<h:panelGrid columns="2" style="margin-bottom:10px">
<h:outputLabel for="firstname" value="Firstname:" />
<p:inputText id="firstname" value="#{subjectController.attributeValue}" />
</h:panelGrid>
<p:commandButton id="submitButton" value="Submit" update=":form:display :form:firstname" action="#{subjectController.saveUpdateSubjectAttributeValue}" oncomplete="PF('dlg').hide();"/>
<p:defaultCommand target="submitButton"></p:defaultCommand>
</p:dialog>
<p:outputPanel id="display" style="display:block;margin-top:10px;">
<h:outputText id="name" value="Hello #{subjectController.attributeValue}" rendered="#{not empty subjectController.attributeValue}"/>
</p:outputPanel>
</h:form>
</h:body>
The .xhtml file that I originally have contains a number of other dialogs and command buttons. When i used the same code in that file it does not work properly. By not working properly I mean to say that when enter key or submit button is pressed the value entered by the user is not set in the corresponding setter of the inputText in the managed bean. To call the setter before pressing the enter key or button I need to use p:ajax inside p:inputText tag. I tried to use p:ajax events such as "mouseout", "blur", "change" etc. They work for the submit button but not for the enter key. Then I tried "keypress" and "keyup" etc. They worked for both but the setter for the value in the p:inputText was called on each key press which was not desired.
My first question:
If the sample code is working fine in a separate file why doesn't it work when I have other dialogs or commandbuttons in the same file. In both the cases I am using the same managed bean. What is the difference?
Assuming that the problem may be caused using more than one dialogs in the same file, I thought of declaring these dialogs in separate files such that I have
A.xhtml , B.xhtml, C.xhtml pages which contain the actual content and whenever I need to open a dialog the required dialog is located in file such as dialog.xhtml. Being a beginner in JSF, Primefaces and Ajax I was confused about how to do this. Searching on the internet I found this post relevant PrimeFaces dialog lazy loading (dynamic="true") does not work?. But in this case, p:dialog is located on the same page but the content contained in this dialog is located in another file which is included using ui:include. I tried this but it shows the same behavior.
My Second Question:
Is there any way to programmatically open a dialog from another file e.g. if I have a p:commandButton in A.xhtml and p:dialog in the same file I can do this using
<p:commandButton id="submitButton" value="Submit" update=":form:display :form:firstname" action="#{subjectController.saveUpdateSubjectAttributeValue}" oncomplete="PF('dlg').hide();"/>
and in the corresponding subjectController I have
saveUpdateSubjectAttributeValue(){
RequestContext context = RequestContext.getCurrentInstance();
context.openDialog("openDialog");
// or
context.execute("openDialog");
}
But what if the "openDialog" is located in B.xhtml?
What I understand, I can use enclose p:dialog in a ui:composition (in B.xhtml) and and use ui:include in A.xhtml. But I am confused in how and where to call openDialog.open() or openDialog.hide()?
I've tried to replicate the behavior you posted here and I believe that the cause is probably somewhere else as mentioned by Yipitalp.
Anyway, here are the sample code I used that might do what you expect (Primefaces 4):
The Managed Bean
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import org.primefaces.context.RequestContext;
#ManagedBean
#ViewScoped
public class DialogBean implements Serializable {
private String attribute1;
private String attribute2;
private String attribute3;
private String dlg;
public void openDialog() {
RequestContext context = RequestContext.getCurrentInstance();
context.execute("PF('" + dlg + "').show()");
}
public String getAttribute1() {
return attribute1;
}
public void setAttribute1(String attribute1) {
this.attribute1 = attribute1;
}
public String getAttribute2() {
return attribute2;
}
public void setAttribute2(String attribute2) {
this.attribute2 = attribute2;
}
public String getAttribute3() {
return attribute3;
}
public void setAttribute3(String attribute3) {
this.attribute3 = attribute3;
}
public String getDlg() {
return dlg;
}
public void setDlg(String dlg) {
this.dlg = dlg;
}
}
The view
Note that I use a different form for every dialog in the view.
<h:form>
<h:panelGrid columns="2" style="margin-bottom:10px">
<h:outputLabel for="dlg" value="Dlg:" />
<p:selectOneMenu id="dlg" value="#{dialogBean.dlg}" >
<f:selectItem itemLabel="dlg1" itemValue="dlg1" />
<f:selectItem itemLabel="dlg2" itemValue="dlg2" />
<f:selectItem itemLabel="dlg3" itemValue="dlg3" />
</p:selectOneMenu>
</h:panelGrid>
<p:commandButton id="submitButton" value="Submit" action="#{dialogBean.openDialog}"/>
<p:defaultCommand target="submitButton" />
</h:form>
<p:button id="showDialogButton1" value="Show 1" onclick="PF('dlg1').show();
return false;" />
<p:button id="showDialogButton2" value="Show 2" onclick="PF('dlg2').show();
return false;" />
<p:button id="showDialogButton3" value="Show 3" onclick="PF('dlg3').show();
return false;" />
<br />
<p:dialog header="Enter FirstName" widgetVar="dlg1" resizable="false">
<h:form>
<h:panelGrid columns="2" style="margin-bottom:10px">
<h:outputLabel for="firstname" value="Firstname:" />
<p:inputText id="firstname" value="#{dialogBean.attribute1}" />
</h:panelGrid>
<p:commandButton id="submitButton" value="Submit" oncomplete="PF('dlg1').hide();"/>
<p:defaultCommand target="submitButton" />
</h:form>
</p:dialog>
<p:dialog header="Enter FirstName" widgetVar="dlg2" resizable="false">
<h:form>
<h:panelGrid columns="2" style="margin-bottom:10px">
<h:outputLabel for="firstname" value="Firstname:" />
<p:inputText id="firstname" value="#{dialogBean.attribute2}" />
</h:panelGrid>
<p:commandButton id="submitButton" value="Submit" oncomplete="PF('dlg2').hide();"/>
<p:defaultCommand target="submitButton" />
</h:form>
</p:dialog>
<p:dialog header="Enter FirstName" widgetVar="dlg3" resizable="false">
<h:form>
<h:panelGrid columns="2" style="margin-bottom:10px">
<h:outputLabel for="firstname" value="Firstname:" />
<p:inputText id="firstname" value="#{dialogBean.attribute3}" />
</h:panelGrid>
<p:commandButton id="submitButton" value="Submit" oncomplete="PF('dlg3').hide();"/>
<p:defaultCommand target="submitButton" />
</h:form>
</p:dialog>
<p:outputPanel autoUpdate="true" style="border: 1px solid black; margin-top:10px;">
Value 1:
<h:outputText id="v1" value="#{dialogBean.attribute1}" />
<br />
Value 2:
<h:outputText id="v2" value="#{dialogBean.attribute2}" />
<br />
Value 3:
<h:outputText id="v3" value="#{dialogBean.attribute3}" />
</p:outputPanel>
I hope that will give you some clue!
I was able to solve major part of my problems using DialogFramework. I have a Menu.xhtml page, it contains p:tieredMenu in p:layoutUnit with position="north" using which I select which page to open. Depending on the selection, the p:layoutUnit with position="center" includes that page using ui:include. The Menu.xhtml page contains a h:form with id="form" inside h:body and everything else is placed inside this h:form. There are a number of pages that can be included inside the <p:layoutUnit position="center"> depending upon the selection. One of them is Person.xhtml(containing everything enclosed inside a ui:composition ). It contains a p:fieldset. Inside p:fieldset there are 3 p:dataTable. Outside this p:fieldset I have placed 3 p:contextMenu one for each of those datatables. Inside one of those p:contextMenu I have placed
<p:menuitem value="Update" actionListener="#{controller.updateAttributeValue}" />
and the corresponding function contains
public void updateAttributeValue(){
System.out.println("update attribute value");
RequestContext context = RequestContext.getCurrentInstance();
context.openDialog("selectCar2");
this.attributeValue = null;
}
selectCar2.xhtml contains the following code
<h:body>
<h:form>
<h:panelGrid id="updateAttributeValuePanel" columns="2" style="margin-bottom:10px">
<h:outputLabel value="Attribute Value " />
<p:inputText id="attributeValue" value="#{controller.attributeValue}" required="true" />
</h:panelGrid>
<p:commandButton id="saveUpdateAttributeValue" value="Submit" actionListener="#{controller.saveUpdateAttributeValue}"
/>
<p:commandButton id="cancelUpdateAttributeValue" value="Cancel "
action="#{controller.cancelUpdateAttributeValue}"
/>
<p:defaultCommand target="saveUpdateAttributeValue" />
</h:form>
</h:body>
The corresponding save function is as follows
public void saveUpdateAttributeValue(){
RequestContext context = RequestContext.getCurrentInstance();
System.out.println("this.attributevalue = " + this.attributeValue);
////save value in database
this.attributeValue = null;
context.update(":form:resourceAttributeValueDataTable");
//also tried context.update("resourceAttributeValueDataTable");
context.closeDialog(this.attributeValue);
}
and
public void cancelUpdateAttributeValue(){
RequestContext context = RequestContext.getCurrentInstance();
context.closeDialog(this.attributeValue);
System.out.println("cancel update attribute value");
this.attributeValue = null;
System.out.println("this.attributevalue = " + this.attributeValue);
}
The dialog opens and the value is successfully saved in the database. The only problem now is that the corresponding datatable is not updated and I need to refresh the page to see the updated value. previously my dialog was also in the same page outside the p:fieldset and I was not using h:form inside dialog so I was updating the datatable as
<p:commandButton id="saveUpdateAttributeValue" value="Submit" actionListener="#{controller.saveUpdateAttributeValue}"
update = ":form:attributeValueDataTable "/>
But now they are in two different files and two different forms so I am not sure how to update in this case? I have tried to use
context.update(":form:resourceAttributeValueDataTable");
//or
context.update("resourceAttributeValueDataTable");
but the datatable is not updated. Any help will be highly appreciated.

Dynamic input fields (values) reset on remove item/field

I have a dynamically expansible table with an add and remove button:
<h:form>
<h:dataTable id="tblFields" value="#{bean.fields}" var="field">
<h:column>
<h:inputText value="#{field.value}" />
</h:column>
<h:column>
<h:inputText value="#{field.value2}" />
</h:column>
<h:column>
<h:inputText value="#{field.value3}" />
</h:column>
<h:column>
<h:commandButton value="Remove">
<f:ajax listener="#{bean.onButtonRemoveFieldClick(field)}" immediate="true" render="#form" />
</h:commandButton>
</h:column>
</h:dataTable>
<h:commandButton value="Add">
<f:ajax listener="#{bean.onButtonAddFieldClick}" execute="#form" render="tblFields" />
</h:commandButton>
</h:form>
This is the associated backing bean:
#Named
#ViewScoped
public class Bean {
private List<Field> fields;
#PostConstruct
public void init() {
fields = new ArrayList();
fields.add(new Field());
}
public List<Field> getFields() {
return fields;
}
public void setFields(List<Field> fields) {
this.fields = fields;
}
public void onButtonRemoveFieldClick(Field field) {
fields.remove(field);
}
public void onButtonAddFieldClick() {
fields.add(new Field());
}
}
The use case is as follows:
Press the add button multiple times.
Fill out all values.
Press the remove button of one random row.
After that, all values filled so far disappears and show up blank. How can I keep them filled after pressing the remove button?
It's because you're in the remove button ajax-updating the entire form without processing the newly submitted input values. The immediate="true" on ajax listener skips the processing of all input components which do not have immediate="true" set. You need to remove the attribtue. The absence of execute attribute will cause only the current component (#this) to be processed by default. You need to explicitly specify #form.
So, just do the same as in your add button. Replace immediate="true" by execute="#form".
<f:ajax listener="#{bean.onButtonRemoveFieldClick(field)}" execute="#form" render="#form" />

Primefaces tabview: set the active index on tab change

I've got a tab view that contains two tab.
When I switch from tab 1 to tab 2, I'm calling some code that executes a validation and updates some values. Depending on the result of this validation, I would like to stay on tab 1, or go to tab 2, and refresh the tabs' content.
My tabview:
<h:form id="form">
<p:tabView id="tabview" activeIndex="#{ctrl.idx}" dynamic="true" cache="false">
<p:ajax event="tabChange" listener="#{ctrl.doStuff}" update=":form:tabview"/>
<p:tab title="Tab 1" id="t1">
<h:panelGrid columns="1" cellpadding="10">
<h:outputText value="#{ctrl.s1}"/>
</h:panelGrid>
</p:tab>
<p:tab title="Tab 2" id="t2">
<h:panelGrid columns="1" cellpadding="10">
<h:outputText value="#{ctrl.s2}"/>
</h:panelGrid>
</p:tab>
</p:tabView>
</h:form>
My test code that simly changes the values:
public void doStuff() {
s1 = String.valueOf(Math.random());
s2 = String.valueOf(Math.random());
}
I thought that changing the active tab index in my method would be enough, like that:
public void doStuff() {
// ...
idx = 0;
}
On tabChange event, the method is called but the tabview components goes to the clicked tab, ignoring the idx new value.
I thought adding an update attribute to p:ajax would render the whole tabview but only the tabs and/or the tabs' content is re rendered.
And weirdest of all, if I change update=":form:tabview" to update=":form" or update="#form", I only receive the tab's content in the ajax response -> the component disappears from the page!
My bean is viewscoped, I'm using Primefaces 3.5, JSF 2.1 and Tomcat 7.
Any idea? Thanks.
Try to bind your TabView to server side component instance in your backing bean.
1.Add TabView component instance to your backing bean
org.primefaces.component.tabview.TabView tabview=null;
and coresponding getter and setter
public TabView getTabview() {
return tabview;
}
public void setTabview(TabView tabview) {
this.tabview = tabview;
}
2.Bind server side instance to your TabView
<p:tabView id="tabview" binding=#{yourBean.tabview} dynamic="true" cache="false">
...
</p:tabView>
3.Modify your doStuff() method
public void doStuff() {
// ...
//idx = 0;
tabview.setActiveIndex(0);
}
And it will hopefully do the trick.
i easy fix this with:
public void onSPTabChange(TabChangeEvent event)
{
TabView tabView = (TabView) event.getComponent();
currentData.setSP_Index(tabView.getChildren().indexOf(event.getTab())+1);
}
in currentdata i have property SP_Index with number of tab (first,second....)
<p:tabView id="tabView" styleClass="tabView">
<p:ajax event="tabChange" listener="#{dataAccess.onSPTabChange}" />
....
and add jquery script
<script>
$("#tabView li:nth-child(#{currentData.SP_Index})").click();
</script>
Try to keep your tabview in panelgrid like this way and update this h:panelgrid
h:panelGrid id="mainPanel">
<p:tabView id="tabview" activeIndex="#{ctrl.idx}" dynamic="true" cache="false">
<p:ajax event="tabChange" listener="#{ctrl.doStuff}" update=":form:mainPanel"/>
<p:tab title="Tab 1" id="t1">
<h:panelGrid columns="1" cellpadding="10">
<h:outputText value="#{ctrl.s1}"/>
</h:panelGrid>
</p:tab>
<p:tab title="Tab 2" id="t2">
<h:panelGrid columns="1" cellpadding="10">
<h:outputText value="#{ctrl.s2}"/>
</h:panelGrid>
</p:tab>
</p:tabView>
</h:panelGrid>

Resources