pe:inputNumber value resetting to initial value inside p:tab - jsf

I have a <p:tabView> on my screen where one of the tabs(<p:tab>) has several <pe:inputNumber> with minValue attribute set to -9999999999.99. When I enter any value be it positive or negative and switch between the tabs, the input value resets to its initial value whereas for the inputs with no minValue set, it retains the entered value after switching between the tabs.
Is there attribute i am missing to set ? Or is there a workaround for the same?
Edit : I'm using primefaces 5.3 and primefaces-extensions 4.0.0. My code for tabs is as shown below :
<p:tabView id="sections" style="width:inherit;background-color: #F0F0F0;">
<p:ajax event="tabChange" listener="#{tabbedViewManagedBean.onTabChange}" />
<p:ajax event="tabClose" listener="#{tabbedViewManagedBean.onTabClose}" />
<p:tab title="First Tab" id="firsttab">
<ui:include src="firsttab.xhtml" />
</p:tab>
<p:tab title="Second Tab" id="secondtab">
<ui:include src="secondtab.xhtml" />
</p:tab>
</p:tabView>
The tabbed view managed bean gets data for that tab when switching between the tabs. Each tab has its own session scoped managed beans.
The code for secondtab.xhtml is :
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:p="http://primefaces.org/ui"
xmlns:pe="http://primefaces.org/ui/extensions">
<h:outputText value="Net Loss :" />
<pe:inputNumber value="#{secondTabMB.netLoss}"
symbol="$ " minValue="-99999999999999.99" />
</ui:composition>
Here's how my screen looks

This may be helps:
<pe:inputNumber value="#{secondTabMB.netLoss}"
symbol="$ " minValue="-99999999999999.99">
<p:ajax event="blur" global="false" />
</pe:inputNumber>

I tried to recreate your problem with this code, but the code below works as expected. I can switch tabs without losing values:
bean
#ManagedBean
#ViewScoped
public class Test {
private Double input1;
private Double input2;
//Getters & Setters
}
html
<h:form>
<p:tabView>
<p:tab title="Input1">
<h:outputText value="Net Loss :" />
<div class="form-element-wrapper">
<pe:inputNumber value="#{test.input1}" symbol="$ " >
<p:ajax process="#this"/>
</pe:inputNumber>
</div>
</p:tab>
<p:tab title="Input2">
<h:outputText value="Net Loss :" />
<div class="form-element-wrapper">
<pe:inputNumber value="#{test.input2}" symbol="$ " minValue="-99999999999999.99" >
<p:ajax process="#this"/>
</pe:inputNumber>
</div>
</p:tab>
</p:tabView>
</h:form>
I added process="#this" just for doing an ajax submit on losing focus.
Can u provide the following code from your ajax request?:
<p:ajax event="tabChange" listener="#{tabbedViewManagedBean.onTabChange}" />

Related

Omit validation for p:selectOneMenu, for Ajax requests

I have a Jsf page with a fragment with <p:selectOneMenu/> (Prime faces) and an Ajax associated with it. It have the default select item "--- Select One ---" and others items that were created dynamically.
This field is required, so if users submit the form without select, the page show a error message.
The problem occurs when I select one of this others options and go back selecting "--- Select One ---" again. Then the page shows the required field message, even before I submit the form. I try different ways of immediate in <p:ajax> and <p:selectOneMenu> tags but none of them has the expected behavior.
The <p:messages> is declared as below:
-- list.xhtml
<p:messages id="messages" autoUpdate="true" closable="true" escape="false" />
<.... include fragment.xhtml ....>
And the fragment:
-- fragment.xhtml
<p:selectOneMenu id="selectTipoCarro"
value="#{carroBean.carro.tipoCarroEnum}"
required="true">
<f:selectItems value="#{carroBean.listaSelectItemTipoCarroInclusao}" />
<p:ajax update="outputInicioVigenciaWrapper outputLabelCalendarInicioVigenciaWrapper"
listener="#{carroBean.aoMudarTipoCarro}" />
</p:selectOneMenu>
<h:panelGroup id="outputLabelCalendarInicioVigenciaWrapper">
<h:outputLabel id="outputLabelCalendarInicioVigencia"
rendered="#{carroBean.edicaoDataInicioVigenciaDisponivel}"
for="calendarInicioVigencia">
<span>*
#{labels['carro.inicio.vigencia']}: </span>
<p:calendar id="calendarInicioVigencia"
value="#{carroBean.carro.dataInicioVigencia}"
showOn="button"
pattern="dd/MM/yyyy" mask="true"
required="true"/>
</h:outputLabel>
</h:panelGroup>
<h:panelGroup id="outputInicioVigenciaWrapper">
<h:outputLabel for="outputInicioVigencia"
rendered="#{not carroBean.edicaoDataInicioVigenciaDisponivel}">
<span aria-live="polite">
<h:outputText id="outputInicioVigencia"
value="#{carroBean.carro.dataInicioVigencia}"
styleClass="dataFormat"
</h:outputText>
</span>
</h:outputLabel>
</h:panelGroup>
private SelectItem obterSelectItemSelecione() {
SelectItem selectItem = new SelectItem("", "-- Select One --");
return selectItem;
}
private void preencherListaSelectItemTipoCarro(List<SelectItem> select, TipoCarroEnum[] tiposCarrosConsiderados) {
select.clear();
select.add(obterSelectItemSelecione());
for (TipoCarroEnum tipoCarro : tiposCarrosConsiderados) {
select.add(new SelectItem(tipoCarro, tipoCarro.getNome()));
}
}
public void aoMudarTipoCarro() {
getCarro().setDataInicioVigencia(carroService.obterProximaDataInicioVigenciaDisponivel(getCarro().getTipoCarroEnum()));
}
That's the expected behaviour. When adding a p:ajax tag to your p:selectOneMenu you make the value be processed everytime the user changes the input, so it will be validated and rejected if you mark it as required. My favourite workaround for this cases is to include a request param in the button to submit the whole form and check for it in the required attribute. That's it:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:comp="http://java.sun.com/jsf/composite/comp"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head />
<h:body>
<h:form>
<p:messages autoUpdate="true" />
<p:selectOneMenu value="#{val}"
required="#{param['validate']}">
<p:ajax event="change" />
<f:selectItem itemLabel="None" noSelectionOption="true" />
<f:selectItem itemLabel="val1" itemValue="val1" />
</p:selectOneMenu>
<p:commandButton value="Submit" ajax="false">
<f:param name="validate" value="true" />
</p:commandButton>
</h:form>
</h:body>
</html>
See also:
Conditionally skip JSF validation but perform model updates
Explanation
This happens because you have a p:messages component with autoUpdate set to true and you have attached p:ajax to your selectOneMenu so anytime your value changes, p:messages is updated. Therefore, due to the use of required="true" an error messages is shown as soon as you have selected "--- Select One ---".
Solution
Add ignoreAutoUpdate="true" to your p:ajax or
Remove autoUpdate="true" if not necessary

tabView in PrimeFaces 5.0 doesn't call tabChange event

I use PrimeFaces 5.0 and jsf 2.2. Here is my page that contains PrimeFaces tabview
<h:panelGroup layout="block" style="position:absolute;top:60px;width:100%;">
<p:tabView id="tabs" activeIndex="#{TabsManagerBean.activeIndex}" onTabShow="$('#tvlistr').click();" dynamic="true"
value="#{TabsManagerBean.tabs}" var="tab">
<p:ajax event="tabChange" listener="#{TabsManagerBean.onTabChange}" />
<p:tab title="#{tab}" titleStyle="width:180px" />
</p:tabView>
<p:commandLink id="tvlistr" style="display:none;" action="#{TabsManagerBean.navigate}"/>
</h:panelGroup>
My onTabChange method
public void onTabChange(TabChangeEvent evt) {
logger.debug("Tab changed to: {}.", evt.getData());
selectedTab = (String) evt.getData();
...
}
and the problem that this method isn't called. i need this method to be called before
<p:commandLink id="tvlistr" style="display:none;" action="#{TabsManagerBean.navigate}"/>
Updated: here is my h:form
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.org/ui">
<f:view locale="en">
<h:head>
<title>#{appMsg.common_pms}</title>
<!-- main JavaScript file -->
<h:outputScript name="js/main.js" />
</h:head>
<h:body>
<h:form id="formId" prependId="false">
<ui:include src="progressbar.xhtml" />
<h:panelGroup id="header" layout="block" style="position:absolute;top:0;width:100%;height:90px;">
<ui:include src="header.xhtml" />
</h:panelGroup>
<h:panelGroup layout="block" style="position:absolute;top:60px;width:100%;">
<p:tabView id="tabs" activeIndex="#{TabsManagerBean.activeIndex}" onTabShow="$('#tvlistr').click();" dynamic="true"
value="#{TabsManagerBean.tabs}" var="tab">
<p:ajax event="tabChange" listener="#{TabsManagerBean.onTabChange}" />
<p:tab title="#{tab}" titleStyle="width:180px" />
</p:tabView>
<h:commandLink id="tvlistr" style="display:none;" action="#{TabsManagerBean.navigate}">
<f:ajax event="action" />
</h:commandLink>
</h:panelGroup>
<h:panelGroup id="footer" layout="block" style="position:absolute;height:20px;width:100%;bottom:0;background-color: #005696">
<ui:include src="/templates/version.xhtml" />
</h:panelGroup>
</h:form>
</h:body>
</f:view>
I had a similar problem with Primefaces 5.1
As long as i put the tabview into a form everything worked fine.
But because i wanted to use seperate forms in my tabs i had to remove the surrounding form of the tabview to avoid nested forms.
Without the surrounding form the ajax event didn´t get triggered any more when changing the tab.
My solution was to use a remotecommand in a form parallel to the tabview.
The remotecommand is triggered by the onTabChange attribute of the tabview element.
At that call i forwarded the index parameter to the global request parameters.
<p:tabView id="rootTabMenu" styleClass="tabcontainer" prependId="false"
activeIndex="#{sessionData.activeTabIndex}" widgetVar="rootTabMenu"
onTabChange="tabChangeHelper([{name: 'activeIndex', value: index}])">
// Tabs...
</p:tabView>
<h:form id="tabChangeHelperForm">
<p:remoteCommand name="tabChangeHelper" actionListener="#{sessionData.onTabChange()}" />
</h:form>
In the backing bean i catched the value again from the request parameter map and set the active index.
public void onTabChange()
{
FacesContext context = FacesContext.getCurrentInstance();
Map<String, String> paramMap = context.getExternalContext().getRequestParameterMap();
String paramIndex = paramMap.get("activeIndex");
setActiveTabIndex(Integer.valueOf(paramIndex));
System.out.println("Active index changed to " + activeTabIndex);
}
Hope that can help you
This is likely a bug related to dynamically built tabs. Removing the "var" and "value" and presenting static tags will cause the listener to fire properly. Might want to file a bug report.
<p:tabView id="tabs" activeIndex="#{TabsManagerBean.activeIndex}" onTabShow="$('#tvlistr').click();" dynamic="true">
<p:ajax event="tabChange" listener="#{TabsManagerBean.onTabChange}" />
<p:tab title="First tab" titleStyle="width:180px" />
<p:tab title="Second tab" titleStyle="width:180px" />
</p:tabView>

don't get the values from input text

i have a serious problem with jsf tabview and form
inside my tabview i have to input text and submit button whenever i submit i always have a empty value.
<h:form id="form">
<p:tab id="tabview" title="Ressources Humaines">
<p:tabView activeIndex="#{SelectBean.activeTab}" value="#{SelectBean.types}" var="item" >
<p:ajax event="tabChange" listener="#{SelectBean.onTabChange}" update=":form" />
<p:tab title="#{item}">
<p:tabView id="tab" activeIndex="#{SelectBean.other}" value="#{SelectBean.res}" var="rr">
<p:ajax event="tabChange" listener="#{SelectBean.onTabChange1}" />
<p:tab title="#{rr.nom_ressource}">
<p:panel rendered ="#{SelectBean.bol}" closable="true" toggleable="true" styleClass="outPanel">
<p:growl id="growl" showDetail="true" />
<h:outputLabel value="Nom " />
<h:inputText value="#{SelectBean.nom}" />
<br/>
<h:outputLabel value="Experience " />
<h:inputText value="#{SelectBean.exp}" />
<br/>
<h:commandButton immediate="true" value="Modifier" action="#{SelectBean.ok}"/>
</p:panel>
</p:tab>
</p:tabView>
</p:tab>
</p:tabView>
</h:form>
the SelectBean.nom and SelecBean.exp are always empty any help please
The problem is with your
<h:commandButton immediate="true" value="Modifier" action="#{SelectBean.ok}"/>
The immediate attribute action method causes JSF to go directly to the render phase 'of the same view' by calling facesContext.renderResponse(), then the components will behave as they do for a validation failure - by displaying the value cached in the component rather than fetching data from the backing bean.
Here is a list of possible solutions

JSF2 - Primefaces - Partial update with command button not works when updating a nested panel

I’m trying to update a part of my page using the following command:
<p:commandButton id="bntNewAddress" immediate="true"
value="New Address" disabled="false" icon="ui-icon-document"
process="#this" update=":main_form:createPanelDetailsAddress"
action="#{issuerComponent.initAddNewAddress}">
</p:commandButton>
When I click the button, the panel "createPanelDetailsAddress" is not updated. On the other side when I use update=":main_form”, the panel is updated (but all other panels inside the main_form are updated also)
The panel I want to update is included in a panel named “createPanel”.
Could anyone have idea why update=":main_form:createPanelDetailsAddress" doesn't work in my case ?
I use primefaces3.5 and Mojarra JSF 2.1.7
Here is the code I used:
public String initAddNewAddress(){
renderCreatePanelDetailsAddress = true;
return null;
}
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui" template="/template.xhtml">
<ui:define name="content">
<h:form id="main_form">
<p:panel id="createPanel" rendered="true">
<p:messages id="msgCreate" />
<p:panel id="createPanelDetails"
header="#{issuerMsgs['issuer.createArea.title']}">
<h:panelGrid border="0" columns="6">
<h:outputText value="#{issuerMsgs['issuer.issuerCode.title']}:" />
<p:inputText required="true"
value="#{issuerComponent.updateIssuer.issuerCode}"
label="issuer_issuerCode">
</p:inputText>
<h:outputText value="#{issuerMsgs['issuer.description.title']}:" />
<p:inputText required="true"
value="#{issuerComponent.updateIssuer.description}"
label="issuer_description">
</p:inputText>
</h:panelGrid>
</p:panel>
<p:spacer height="10" />
<p:panel id="panelListAddress"
header="#{addressMsgs['address.createArea.title']}">
<p:dataTable id="addresslist" var="address"
value="#{issuerComponent.addressList}" paginator="false" rows="10">
<p:column>
<f:facet name="header">
<h:outputText value="#{addressMsgs['address.tel.title']}" />
</f:facet>
<h:outputText value="#{address.tel}" />
</p:column>
</p:dataTable>
<p:spacer height="22" width="0" />
<p:commandButton id="bntNewAddress" immediate="true"
value="New Address" disabled="false" icon="ui-icon-document"
process="#this" update=":main_form:createPanelDetailsAddress"
action="#{issuerComponent.initAddNewAddress}">
</p:commandButton>
</p:panel>
<p:panel id="createPanelDetailsAddress"
header="#{addressMsgs['address.createArea.title']}"
rendered="#{issuerComponent.renderCreatePanelDetailsAddress}">
<ui:include src="createAddress.xhtml"></ui:include>
<p:commandButton value="Add"
rendered="#{issuerComponent.renderBtnAddAddress}" disabled="false"
icon="ui-icon-document" process="#this,createPanelDetailsAddress"
update=":main_form" action="#{issuerComponent.addNewAddress}"
actionListener="#{addressComponent.addNewComposite}">
<f:setPropertyActionListener
value="#{addressComponent.updateAddress}"
target="#{issuerComponent.address}" />
</p:commandButton>
</p:panel>
</p:panel>
</h:form>
</ui:define>
</ui:composition>
Your update will fail because
rendered="#{issuerComponent.renderCreatePanelDetailsAddress}"
will evaluate to false the first time the view is rendered. As a result the component is not in the DOM tree the first time the view is rendered.
Ajax updates work by locating a specific component (by id) in the DOM and replacing it with new markup. Your panel was never in the DOM to begin with, so there's nothing to update with ajax.
To remedy, you need to wrap the <p:panel/>with another component and make that component the target of your ajax update
<p:outputPanel id="container" layout="none">
<p:panel id="createPanelDetailsAddress" header="# addressMsgs['address.createArea.title']}" rendered="#issuerComponent.renderCreatePanelDetailsAddress}">
<ui:include src="createAddress.xhtml"></ui:include>
<p:commandButton value="Add"
rendered="#{issuerComponent.renderBtnAddAddress}" disabled="false"
icon="ui-icon-document" process="#this,createPanelDetailsAddress"
update=":main_form" action="#{issuerComponent.addNewAddress}"
actionListener="#{addressComponent.addNewComposite}">
<f:setPropertyActionListener
value="#{addressComponent.updateAddress}"
target="#{issuerComponent.address}" />
</p:commandButton>
</p:panel>
</p:outputPanel>

Init method gets called twice in #Viewscoped bean

I am using schedule component of Primefaces. I am filling it with values from database and when the user selects sth from the selectonemenu an ajax event is triggered (I tried to put just the related code, if there is sth missing pls remind me):
xhtml:
<h:outputText value="Scope :" />
<h:selectOneMenu id="scope" value="#{scheduleView.scope}">
<f:selectItems value="#{lookup.scopeCombo}"/>
<p:ajax process="scope" update="schedule, scheduleForm, scheduleFormPG" listener="#{scheduleView.changeScopeType()}"/>
</h:selectOneMenu>
<p:schedule id="schedule" value="#{scheduleView.model}" editable="true"/>
Backing bean:
#ManagedBean
#ViewScoped
public class ScheduleView implements Serializable {
#PostConstruct
public void init() {
System.out.println("Init ");
scopeChange();
}
public void scopeChange(String scope){
System.out.println("scopeChange ");
model.clear();
events = (List<Event>) commonServis.bringEverythingByCriteria(Event.class, "scope" , scope);
for(int i= 0; i<events.size();i++){
model.addEvent(new DefaultScheduleEvent(events.get(i).getAd(), events.get(i).getStartDate(),events.get(i).getEndDate()));
}
public void changeScopeType() {
System.out.println("changeScopeType ");
scopeChange (scope);
}
The output of the above code is:
Init
scopeChange
When the user changes the value in the selectonemenu:
changeScopeType
Init
scopeChange
It is supposed to go into init method just once. But after the changeScopeType function is triggered it gets into the init method and fills the schedule with unrelated data. I thought it might be related to #Postconstruct annotation but I couldn't find any related explanation. Can anyone understand the reason and offer a solution?
Here is the full page:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://prime.primefaces.org/ui"
template="templates/layout.xhtml"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<ui:define name="title">#{labels.schedule}</ui:define>
<ui:define name="content">
<h:form id="scheduleForm">
<h:panelGrid id="scheduleFormPG">
<p:growl id="msgs" />
<p:dialog modal="true" widgetVar="statusDialog" header="Status" draggable="false">
<h:graphicImage value="resources/images/ajax-loader.gif" />
</p:dialog>
<p:dialog showEffect="explode" hideEffect="explode" resizable="false"
header="warning" widgetVar="confirmationErase" appendToBody="true" modal="true">
<h:outputText value="Are you sure?"/>
<br/>
<p:commandButton value="Yes" actionListener="#{scheduleView.deleteEvent(AE)}"
update="msgs, scheduleFormPG, schedule, wrapperPanel"
onstart="statusDialog.show(),confirmationErase.hide()"
oncomplete="statusDialog.hide(), eventDialog.hide()" process="#parent, scope" />
<p:commandButton value="No" onclick="confirmationErase.hide()" type="button" />
</p:dialog>
<h:outputText value="scope :" />
<h:selectOneMenu id="scope" value="#{scheduleView.scope}">
<f:selectItems value="#{lookup.scopeTypeCombo}"/>
<p:ajax process="scope" update="schedule, scheduleForm, scheduleFormPG" listener="#{scheduleView.changeScopeType()}"/>
</h:selectOneMenu>
</h:panelGrid>
<p:schedule onDateSelectUpdate="wrapperPanel"
onEventSelectUpdate="wrapperPanel" onEventSelectComplete="eventDialog.show()" eventSelectListener="#{scheduleView.onEventSelect}"
onDateSelectComplete="eventDialog.show();" dateSelectListener="#{scheduleView.onDateSelect}" id="schedule" value="#{scheduleView.model}" editable="true"/>
<p:dialog id="dialog111" widgetVar="eventDialog" header="Event Information" showEffect="clip" hideEffect="clip">
<p:panel id="wrapperPanel">
<h:panelGrid id="eventDetails" columns="2">
<h:outputLabel for="eventName" value="Event Name *: " />
<p:inputText id="eventName" value="#{scheduleView.event.title}" required="true"/>
<h:outputLabel value="Start Date:" />
<p:calendar id="sKalender" value="#{scheduleView.event.startDate}">
<f:convertDateTime pattern="dd/MM/yyyy" />
</p:calendar>
<h:outputLabel value="End Date:" />
<p:calendar id="eKalender" value="#{scheduleView.event.endDate}">
<f:convertDateTime pattern="dd/MM/yyyy" />
</p:calendar>
<h:outputLabel value="All Day:" />
<h:selectBooleanCheckbox id="allDay" value="#{scheduleView.event.allDay}" />
<h:outputLabel value="scope: " />
<h:selectOneMenu id="scopeChoice" value="#{scheduleView.event.scope}">
<f:selectItems value="#{lookup.scopeTypeCombo}"/>
</h:selectOneMenu>
<p:commandButton onclick="confirmationErase.show()" oncomplete="eventDialog.hide()" update="wrapperPanel, msgs, schedule" type="reset" value="Delete" />
<p:commandButton value="Save" actionListener="#{scheduleView.addEvent(AE)}" process="#parent, scope" update="schedule wrapperPanel msgs scheduleForm" oncomplete="eventDialog.hide();"/>
</h:panelGrid>
</p:panel>
</p:dialog>
</h:form>
</ui:define>
</ui:composition>
The problem was this line of code:
<p:ajax process="scope" update="schedule, scheduleForm, scheduleFormPG" listener="#{scheduleView.changeScopeType()}"/>
update was refreshing the whole page, instead it should've only update schedule. When I change it to:
update="schedule"
the problem solved.
Thanks everyone for their effort.

Resources