Primefaces AccordionPanel validation of inner elements on tabChange/tabClose - jsf

I am using an accordion panel with three tabs.
Each tab has required fields and <p:ajax> tags for accordionPanel:
<p:ajax event="tabChange" update=":contentForm:growl"/>
<p:ajax event="tabClose" update=":contentForm:growl"/>
By default all tabs are closed. When I click to open any tab, it performs vaidation of all inputs in all tabs.
How do I skip field validation and do ajax query during open/close tab?
(I need an Ajax query to save opened tabs indexes to Bean: activeIndex="#{tabBean.activeTabs}")

I have resolved this problem. I have created saver-class:
import javax.faces.event.AjaxBehaviorEvent;
import org.primefaces.component.accordionpanel.AccordionPanel;
public class ActiveIndexSaver {
private String activeTabs = "-1,0";
public String getActiveTabs() {
return activeTabs;
}
public void setActiveTabs(String activeTabs) {
this.activeTabs = activeTabs;
}
public void saveIndexes(AjaxBehaviorEvent abe){
AccordionPanel accordion = (AccordionPanel)abe.getComponent();
activeTabs = accordion.getActiveIndex();
}
}
After that I wrote Inject of the bean above to page-bean and getter for him:
#Inject
private ActiveIndexSaver activeIndexSaver;
....
public ActiveIndexSaver getActiveIndexSaver() {
return activeIndexSaver;
}
And finally, html:
<p:accordionPanel ... activeIndex="#{tabBean.activeIndexSaver.activeTabs}">
<p:ajax event="tabChange" immediate="true" listener="#{tabBean.activeIndexSaver.saveIndexes}"/>
<p:ajax event="tabClose" immediate="true" listener="#{tabBean.activeIndexSaver.saveIndexes}"/>
......

Related

#ConversationScoped bean reconstructed during page-to-page navigation

I just found a strange behavior when I change from one page to another.
I'm using CDI, Jsf 2.2 API 2.2.8, Omnifaces 2.2, Primefaces 5.2, wildfly 8.2.
Most of the controllers and pages work as expected, but some of them, when I access the page, call the method #PostConstruct, which starts the conversation, then, when I leave the page, the #PostConstruct is called again. I realized that something in page.xhtml is the cause, so I started to look for it. But is a strange behaviour anyway.
Following my code and some examples:
Controller which uses abstract class methos like beginconversation() and list()
import javax.inject.Named;
import javax.enterprise.context.ConversationScoped;
#Named
#ConversationScoped
public class PromptConfigurationController extends BaseController<PromptConfiguration> implements Serializable {
public PromptConfigurationController() {
super(PromptConfiguration.class);
}
#PostConstruct
public void init() {
list();
loadFilters();
}
}
Abstract class
public abstract class BaseController<T extends BaseEntity> {
public void list() {
logger.info("list()");
items = getService().findAll(entityClass);
item = null;
beginConversation();
}
protected void beginConversation() {
logger.info("beginConversation()");
if (conversation != null && conversation.isTransient()) {
conversation.begin();
conversation.setTimeout(CONVERSATION_TIMEOUT);
logger.info("Conversation iniciada: " + conversation.getId());
}
}
}
some xhtml pages which I found problem and the solution (when I found) was:
Error:
<f:convertDateTime pattern="#{webChatSearchController.dateHelper.getLocalizedDatePattern()}" />
The method above just return a pattern.
Working
<f:convertDateTime dateStyle="dd/MM/yyyy" pattern="dd/MM/yyyy" />
Error:
<p:commandButton id="commandButton-active" action="#{satisfactionSurveyController.changeQuestionStatus(true)}" update="form-content" binding="#{satisfactionSurveyController.activeButton}" value="#{bundle['common.active.3.message']}">
Working:
<p:commandButton id="commandButton-active" action="#{satisfactionSurveyController.changeQuestionStatus(true)}" update="form-content" value="#{bundle['common.active.3.message']}" disabled="#{satisfactionSurveyController.disableActiveButton}">
The problem was just the "binding".
Error:
<p:dataTable id="dataTable-group-email" var="emailMonitor" value="#{emailMonitorController.listEmailGroup}" selectionMode="single" rowKey="#{emailMonitor}" filteredValue="#{emailMonitorController.listEmailGroupFiltered}">
Working:
<p:dataTable id="dataTable-group-email" var="emailMonitor" value="#{emailMonitorController.listEmailGroup}" selectionMode="single" rowKey="#{emailMonitor}" >
Just removing 'filteredValue' started working. But without it, I can't use the filter properties.
The navigation is made by a menu of primefaces, all the pages are the same logic:
<p:menuitem id="satisfactionSurvey" action="#{satisfactionSurveyController.listPage}" value="#{bundle[satisfactionSurvey.message']}" ajax="false" immediate="true">
<f:param name="nocid" value="true" />
</p:menuitem>
and the Method:
public String listPage() {
return baseViewPath + "/list.xhtml?faces-redirect=true";
}

Auto-updating filter values on DataTable

I'm currently using filters with options list on my lazy loaded DataTables. Everything works just fine except I'd like to be able to reload my filter options depending on currently selected filters.
For example, my DataTable has two fields country and region, and I want to filter
DataTable snippet :
<p:dataTable var="d" widgetVar="personneContactTable" value="#{bean.dataModel}" id="myDataTable" lazy="true">
<p:column sortBy="country" filterBy="country" filterOptions="#{bean.getCountryOptions()}">
[...]
</p:column>
<p:column sortBy="region" filterBy="region" filterOptions="#{bean.getRegionOptions()}">
[...]
</p:column>
</p:dataTable>
And my bean :
#ManagedBean(name = "bean")
#SessionScoped
public class MyBean implements Serializable {
LazyDataModel<MyStuff> dataModel;
String country;
String region;
public SelectItem[] getCountryOptions() {
return service.someMagic();
}
public SelectItem[] getRegionOptions() {
return service.someMoreMagic(country);
}
// + getters, setters, etc.
}
I tried using properties instead of methods, adding <p:ajax event="filter"> tags to try reloading part of the DataTable, but nothing worked. I found http://forum.primefaces.org/viewtopic.php?f=3&t=38087 too, but again not workable solution emerged.
How can I automaticaly refresh my filterOptions? (this is using Primefaces 4 ELITE branch)

t:dataScroller not working correctly on refresh

I'm using t:dataScroller to scroll some data from a t:dataTable and it is working fine except for one thing: every time an action that causes the screen to be refreshed is triggered the t:dataScroller's index is set to 1.
To be more clear: when i'm in the second page (index == 2) and a screen refreshing action triggers, after the refresh, the data of the dataTable is still from index 2 but the dataScroller shows that the page being displayed is the first one.
I'm using the dataScroller this way:
<t:dataScroller for="myDataTable" id="myDataScroller" paginator="true"
paginatorMaxPages="#{myBean.paginatorMxPgs}"
pageCountVar="pgCount" pageIndexVar="#{myBean.curPg}"
actionListener="#{myBean.pgListener}">
<f:facet name="prv">
<h:panelGroup rendered="#{myBean.curPg > 1}" />
</f:facet>
<f:facet name="nxt">
<h:panelGroup rendered="#{myBean.curPg != pgCount}"/>
</f:facet>
</t:dataScroller>
i'm using tomahawk20-1.1.11.jar and myfaces-api-2.0.4.jar
For setting scroller to firstpage set actionlistener on submit button.
<t:commandButton actionListener="#{IFussBean.resetDataScroller}"
action="#{IFussBean.searchLocation}"
image="images/submit-button.png">
</t:commandButton>
Binding:
if it is datatable
<t:dataTable id="data"
headerClass=""
footerClass=""
rowClasses="text_holder"
columnClasses="search_img,search_txt"
var="item"
value="#{IFussBean.searchVideoList}"
preserveDataModel="false"
rows= "6"
binding="#{IFussBean.iFussData}"
>
Declare HtmlDataTable in your Bean,define its setter getter as below:
private HtmlDataTable iFussData;
Getter and setter
public HtmlDataTable getiFussData() {
return iFussData;
}
public void setiFussData(HtmlDataTable iFussData) {
this.iFussData = iFussData;
}
Now define ActionListener Method in Bean:
public void resetDataScroller(ActionEvent e) {
if(iFussData!= null) {
iFussData.setFirst(0);
}
}
Your page will set to first page when you'll do new search.
/**********************************************************************************************************************************/
if you are using <rich:dataGrid> and your scroller is <t:dataScroller> then
<rich:dataGrid
id="data"
var="item"
columns="3"
elements="6"
width="600px"
value="#{IFussBean.searchVideoList}"
binding="#{IFussBean.iFussDataGrid}"
>
Declare HtmlDataGrid in Bean:
private HtmlDataGrid iFussDataGrid;
Its getter and setter
public HtmlDataGrid getiFussDataGrid() {
return iFussDataGrid;
}
public void setiFussDataGrid(HtmlDataGrid iFussDataGrid) {
this.iFussDataGrid = iFussDataGrid;
}
Now define its action listener in Bean which will invoke on pressing command button for search :
public void resetDataScroller(ActionEvent e) {
if(iFussDataGrid != null) {
iFussDataGrid.setFirst(0);
}
}
Invoke ActionListener on command button
<h:commandButton styleClass="submit-button" actionListener="#{IFussBean.resetDataScroller}" action="#{IFussBean.searchLocation}" image="images/submit-button.png"/>
It also give desire result.

JSF Dynamic Rendered Component's Value becomes null when the form is submitted

I have a JSF page which renders a text field depending on the value of a drop down using primefaces ajax listner. The dynamic rendering is done fine. but the problem is once I submit the form the the bound value of that textfield doesn't get bound instead it is shown as null.
this is the part of my JSF only the necessary fields are included here
<h:panelGroup id="textPanel" >
<h:form id="main" prependId="false">
<h:outputText value="WorkFlow ID:" />
<h:selectOneMenu id="workFlows" value="#{workFlowSelectionController.selectedWorkFlowId}" >
<p:ajax event="change" listener="#{workFlowSelectionController.dropDownChange}" update="textPanel"/>
<f:selectItems value="#{workFlowSelectionController.allActiveworkFlows}"/>
</h:selectOneMenu>
<p:inputText value="#{workFlowSelectionController.texField}" rendered="#{workFlowSelectionController.textfieldVisibility}"/>
<p:commandButton ajax="false" value="Next" action="#{workFlowSelectionController.addWorkFlowselectionDetails}"/>
</h:form>
</h:panelGroup>
this is my managed bean
#ManagedBean
#RequestScoped
public class WorkFlowSelectionController {
private boolean textfieldVisibility = false;
private String texField;
public void dropDownChange() {
logger.info("WorkFlowSelectionController.dropDownChange() entered");
if (selectedWorkFlowId != null) {
if (selectedWorkFlowId.equals("-1")) {
textfieldVisibility = true;
operationListStatus = false;
} else {
textfieldVisibility = false;
operationListStatus = true;
}
} else {
textfieldVisibility = false;
operationListStatus = true;
}
public void addWorkFlowselectionDetails() throws CloneNotSupportedException {
System.out.println("Selected Value of Text Field is" + texField);
}
public String getTexField() {
return texField;
}
public void setTexField(String texField) {
this.texField = texField;
}
}
i haven't included the dropdown code of the backing bean. i just need an idea of what i am doing wrong here if i remove the rendered attribute of the textfield it works fine.
thank you
Put the bean in the view scope instead of request scope. A request scoped is recreated on every single HTTP request. The boolean property will default to false again whenever you submit the form, so the submitted value won't be processed then.
#ManagedBean
#ViewScoped
public class WorkFlowSelectionController {
//
}
A view scoped bean will live as long as you're (ajax-) interacting with the same view by returning null or void from action(listener) methods.

primefaces tabView activeIndex issue

I have Primefaces TabView with two Tab like:
<p:tabView dynamic="true" cache="false"
onTabShow="scrollBottom(#{stanzaBean.activeIndex})"
tabChangeListener="#{messaggioBean.onTabChange}"
activeIndex="#{stanzaBean.activeIndex}" >
it works fine, except that when I change the Tab the activeIndex isn't updated on the Server and it returns always the default value.
I'm using primefaces 2.2.1.
Thank you.
Going by the PrimeFaces ShowCase example, if you give each tab an id:
<p:tabView tabChangeListener="#{indexBean.onTabChange}" >
<p:tab title="tab 0" id="tab0"></p:tab>
<p:tab title="tab 1" id="tab1" ></p:tab>
<p:tab title="tab 2" id="tab2"></p:tab>
</p:tabView>
you can get that tab id in the tabChangeListener.
public void onTabChange(TabChangeEvent event) {
System.out.println("tab id = " + event.getTab().getId());
}
Then you'll know which tab was selected.
Edit:
There is an open PrimeFaces issue 1640 TabView: Wrong activeIndex in TabChangeListener, always 0 on the problem you are having.
Edit 2:
With PrimeFaces 5.0 and up the tabChangeListener is no longer available on the tabView element but should be used via an explicit ajax tag with a tabChange event.
<p:tabView id="analysisSections" value="#{analysisBean.analysis.sections}" var="section" activeIndex="#{analysisBean.activeIndex}">
<p:ajax event="tabChange" listener="#{analysisBean.onTabChange}"/>
Also you can directly get index of tab:
public void onTabChange(TabChangeEvent event) {
activeIndex = ((TabView) event.getSource()).getIndex();
}
with all these changes, activeIndex works properly.
this worked for me:
public void onTabChange(TabChangeEvent event) {
Tab activeTab = event.getTab();
tabPanelIndex = ((TabView)event.getSource()).getChildren().indexOf(activeTab);
}
Although the question was related to PrimeFaces 2.2.1, I like to mention that in modern PrimeFaces versions (tested with version 6.2) there is no need to trigger a separate event when attribute dynamic is set to true and cache is set to false. By using this attribute combination the active index is automatically updated on the server when another tab is selected.
Facelet:
<p:tabView activeIndex="#{stanzaBean.activeIndex}"
cache="false"
dynamic="true">
Bean:
#Named
#ViewScoped
public class StanzaBean implements Serializable {
private int activeIndex;
public int getActiveIndex() {
return activeIndex;
}
/**
* Automatically called whenever a tab changes and dynamic="true"
* and cache="false".
*/
public void setActiveIndex(int activeIndex) {
this.activeIndex = activeIndex;
// do other stuff when tab changes
}
}

Resources