JSF + primefaces spinner ajax invoking other submits - ajax

I'm using ajax in spinner to call some action in backing bean.
this is my code:
<b:panel>
<p:dataTable id="orderDataTable" var="order" value="#{orderViewBean.orders}"
widgetVar="ordersDataTable" tableStyle="table-layout: auto;">
<p:column headerText="Created" filterBy="#{order.creationDate}" filterStyle="display: none"
filterMatchMode="contains">
<h:outputText value="#{order.creationDate}"/>
</p:column>
<p:column headerText="Created By" filterBy="#{order.createdBy}" filterStyle="display: none"
filterMatchMode="contains">
<h:outputText value="#{order.createdBy}"/>
</p:column>
</p:dataTable>
<b:panelGrid colSpans="4,4,4">
<b:commandButton action="#{orderViewBean.previousPage}" value="Previous"
look="primary" process="#this:uploadOrderDataPanel" styleClass="pull-left"
disabled="#{!orderViewBean.page.hasPrevious()}" type="submit">
<p:ajax immediate="true" update=":companyOrdersForm"/>
</b:commandButton>
<b:row>
<div class="text-center">
<h:outputLabel value="Page"/>
<p:spinner value="#{orderViewBean.currentPage}" size="3"
min="#{orderViewBean.page.totalPages > 0 ? 1 : 0}"
max="#{orderViewBean.page.totalPages}">
<p:ajax listener="#{orderViewBean.changePageAjax}"
update="#form" process="#this" immediate="true"/>
</p:spinner>
<h:outputLabel value="Of"/>
<h:outputText value="#{orderViewBean.page.totalPages}"/>
</div>
</b:row>
<b:commandButton action="#{orderViewBean.nextPage}" value="Next"
look="primary" process="#this:uploadOrderDataPanel" styleClass="pull-right"
disabled="#{!orderViewBean.page.hasNext()}" type="submit">
<p:ajax immediate="true" update=":companyOrdersForm"/>
</b:commandButton>
</b:panelGrid>
</b:panel>
When I put some number into spinner and hit enter, then changePageAjax is invoked (this is ok) and also orderViewBean.previousPage (this is not ok). Can I avoid invoking other actions?

Add a partialSubmit="true" attribute on the relevant ajax tags.. From the PF documentation:
PartialSubmit reduces network traffic by only adding the partially processed components to the ajax request post. For big pages with many input components, partialSubmit is extremely useful as it leads to more lightweight requests. Compare the Post Data displayed by the logger for the difference.
See also:
http://www.primefaces.org/showcase/ui/ajax/partialSubmit.xhtml

Related

Richfaces 4 bug in datatable with datascroller validation when empty

I have a screen in my Richfaces application which uses a datatable and datascroller, with validation to ensure that data is filled.
( example to simulate the problem, full example can be found here
<h:form id="articleForm" >
<h:panelGroup layout="block">
<rich:messages globalOnly="true" />
<rich:dataTable value="#{productModifyBean.articles}" var="article" id="articleTable"
rows="15" >
<rich:column headerClass="headerOverflow artNrColumn">
<f:facet name="header">
<h:outputText value="articleNumber" />
</f:facet>
<h:outputText value="#{article.articleNumber}"/>
</rich:column>
<rich:column headerClass="headerOverflow shortNameColumn">
<f:facet name="header">
<h:outputText value="Name" />
</f:facet>
<h:outputText value="#{article.shortName}" />
</rich:column>
<rich:column headerClass="headerOverflow quantityColumn" >
<f:facet name="header">
<h:outputText value="Quantity" />
</f:facet>
<h:inputText value="#{article.quantity}" required="true"
requiredMessage="This is required" converterMessage="Error conversion"
id="modifyArticleFormatQuantity" >
</h:inputText>
<rich:message for="modifyArticleFormatQuantity" errorClass="errorColorRed" />
</rich:column>
</rich:dataTable>
<rich:dataScroller for="articleTable" renderIfSinglePage="false" boundaryControls="show" fastControls="hide" execute="#form" render="articleTable"
stepControls="show" style="float:right;" />
</h:panelGroup>
<br style="clear: both" />
<br style="clear: both" />
<div align="right" style="clear: both">
<a4j:commandButton value="#{msgs['button.modify'] }" styleClass="submitButton"
render="#{facesContext.validationFailed ? '#none' : 'articleForm'}"
actionListener="#{productModifyBean.modifyProduct}">
</a4j:commandButton>
</div>
</h:form>
Data validation should happen when the user presses the submit button ( to save the data) , and when the user using the pagination to go to a different page.
When clicking the submit button after leaving one field empty, the behaviour is normal : it shows an empty field with the remark 'this is required'
However, when instead moving to a different page ( for example clicking on the '2' page button ) , validation happens correctly, but the old value is put back into the screen, thus stating that the value should be filled but showing it filled in with a value.
Anyone have any idea what the reason for this problem could be, and how to resolve it ? Is this a bug in RichFaces, or am I overlooking something ?
I found the solution by trial and error :
If I change the datascroller to use render="#region" , the screen is correctly rendered.
<rich:dataScroller for="articleTable" renderIfSinglePage="false" boundaryControls="show" fastControls="hide" execute="#form" render="articleTable"
stepControls="show" style="float:right;" />

<p:commandButton> won't submit form on first click if <p:inputText> field uses <p:ajax>

I'm having an issue with the following form:
<h:form>
<p:outputPanel autoUpdate="true">
<p:panelGrid columns="2">
<f:facet name="header">
<h:outputText value="Edit a Recycler"/>
</f:facet>
<p:outputLabel value="Recycler Name" for="recyclerName"/>
<p:inputText id="recyclerName" value="#{RecyclerAdmin.editItem.company.companyName}" required="true" requiredMessage="You must name the recycler.">
<p:ajax async="true" />
</p:inputText>
<p:outputLabel value="Zip Code" for="zipCode"/>
<p:inputText id="zipCode" value="#{RecyclerAdmin.editItem.company.primaryAddressId.zip}" required="false">
<p:ajax event="blur" async="true" update="citystate" listener="#{RecyclerAdmin.zipCodeChanged}"/>
</p:inputText>
<p:outputLabel value="City/State"/>
<c:choose>
<c:when test="${RecyclerAdmin.editItem.company.primaryAddressId.city != null and RecyclerAdmin.editItem.company.primaryAddressId.city.length() > 0}">
<h:outputText id="citystate" value="#{RecyclerAdmin.editItem.company.primaryAddressId.city}, #{RecyclerAdmin.editItem.company.primaryAddressId.state}"/>
</c:when>
<c:otherwise>
<p:spacer id="citystate"/>
</c:otherwise>
</c:choose>
<f:facet name="footer">
<p:commandButton id="updatebutton" action="#{RecyclerAdmin.update()}" value="Save" ajax="false"/>
<p:commandButton id="cancelbutton" action="#{RecyclerAdmin.cancel}" value="Cancel" ajax="false" immediate="true"/>
</f:facet>
</p:panelGrid>
</p:outputPanel>
</h:form>
If I make a change to the "Recycler Name" text field, and then immediately click on the save button, the button click highlighting activates, and remains active, but the form does not submit until the button is clicked a second time. If I click somewhere else before clicking on the save button, everything works, and if I remove the ajax async="true" from the recyclerName field, the form also will submit normally, but I need the ajax reference otherwise any changed values in the field are erased when the zipCode field is manipulated.
Any ideas?
The problem was caused by the outputPanel autoUpdate="true" tag. i have added specific update field references to the individual ajax tags and the problem is now gone.
try different event
try removing async=true
p:ajax event="keyup"
http://www.primefaces.org/showcase/ui/ajax/event.xhtml

Primefaces update from inside another form

I'm not sure what's wrong with my HTML code. From what I read, it should work. I even tried using prependId="false" which didn't resolve the problem of not finding the UI Component.
<p:tabView>
<p:tab title="Tab1" id="tab1">
<h:form id="form1" prependId="false">
<p:panelGrid columns="2" id="grid1">
<h:outputLabel for="minDraw" value="Starting draw number:" />
<p:inputText id="minDraw" value="#{LottoMaxBacking.minDraw}" />
<p:commandButton value="Get Frequency From Begining"
actionListener="#{LottoMaxBacking.loadAllDrawFreq}"
update=":form2:freqTable" />
</p:panelGrid>
</h:form>
<h:form id="form2" prependId="false">
<p:dataTable var="entry" value="#{LottoMaxBacking.drawFreqList}"
id="freqTable">
<f:facet name="header">
<h:outputText value="#{LottoMaxBacking.tableHeader}" />
</f:facet>
<p:column sortBy="#{entry.key}" headerText="Ball Number">
<h:outputText value="#{entry.key}" />
</p:column>
<p:column sortBy="#{entry.value}" headerText="Frequency">
<h:outputText value="#{entry.value}" />
</p:column>
</p:dataTable>
</h:form>
</p:tab>
<p:tab title="Tab 2"></p:tab>
</p:tabView>
I tried ":tab1:form2:freqTable", ":freqTable", and "freqTable" but none of them work. When I put both forms together as a single form, it would find the freqTable fine.
OK I finally figured it out after looking at the error message again.
Cannot find component with identifier ":form2:freqTable" referenced from "j_idt54:j_idt56"
idt54 refers to the TabView and idt56 refers to the command button. So it turns out that my button's AJAX update string didn't go far enough original and all my other attempts referred to the wrong parent container. I added an id to p:tabView and changed the update String and it worked.
<p:commandButton value="Get Frequency From Begining"
actionListener="#{LottoMaxBacking.loadAllDrawFreq}"
update="tv:form2:freqTable" />

Keep <p:dialog> open when validation has failed

I have a CRUD page which shows data from a query (a List of domain objects) in a Primefaces datatable.
<p:dataTable
id="negozi"
var="n"
value="#{nController.theListFromQuery}"
rowKey="#{n.id}"
selection="#{nController.selected}"
selectionMode="single">
<p:column headerText="Field1">
<h:outputText value="#{n.f1}" />
</p:column>
<p:column headerText="Field2">
<h:outputText value="#{n.f2}" />
</p:column>
<p:column style="width:4%">
<p:commandButton
actionListener="#{nController.prepareEdit(n)}"
update=":editDialogId"
oncomplete="editDialog.show()"
value="Edit" />
</p:column>
...
By clicking on the edit button a dialog will be shown:
<p:dialog
header="Edit N"
widgetVar="editDialog"
id="editDialogId">
<h:form id="formDialog">
<h:panelGrid id="editDialogTable" columns="2" cellpadding="10" style="margin:0 auto;">
<p:outputLabel for="field1" value="F1:" />
<p:inputText id="field1" value="#{nController.selected.f1}" />
<p:outputLabel for="field2" value="F2:" />
<p:inputText id="field2" value="#{nController.selected.f2}" />
<p:commandButton
value="Confirm"
actionListener="#{nController.doEdit}"
update=":form"
oncomplete="editDialog.hide()"
rendered="#{nController.selected.id!=null}" />
...
It works. Now I want to make F1 a required field.
I add the "required" attribute to the inputText field and what happens?
When I try to confirm the form without the required field, the entity is not edited (that's right) but the dialog is closed (that's NOT right!)
When I reopen the dialog I can see the red highlight on the required (and invalid) field.
What I want is to prevent the dialog closing if the form is invalid.
Do I have to write some JS or will JSF help me?
The PrimeFaces ajax response puts an args object in the scope which has a validationFailed property. You could just make use of it.
oncomplete="if (args && !args.validationFailed) PF('editDialog').hide()"
(the args precheck is necessary to not cause a JS error when an exception is thrown during request)
You could refactor it to a reusable JS function as follows.
oncomplete="hideDialogOnSuccess(args, 'editDialog')"
function hideDialogOnSuccess(args, dialogWidgetVar) {
if (args && !args.validationFailed) {
PF(dialogWidgetVar).hide();
}
}
this post is now three years old, but I have found helpful, so my findings may help others.
In PF 5.x at least, it seems that the solution provided by BalusC has to be modified in two ways. (1) add the "args" argument to the call in oncomplete event hander, and (2) use the PF primefaces primitive to identify the widget in PF tables. Here is the code I am using:
oncomplete="hideDialogOnSuccess(args, PF('editDialog'))"
function hideDialogOnSuccess(args, dialogWidgetVar) {
if (args && !args.validationFailed) {
dialogWidgetVar.hide();
}
}
I believe this is the cleanest solution.
Doing this you don't need to change your buttons code.
This solution overrides the hide function prototype.
$(document).ready(function() {
PrimeFaces.widget.Dialog.prototype.originalHide = PrimeFaces.widget.Dialog.prototype.hide; // keep a reference to the original hide()
PrimeFaces.widget.Dialog.prototype.hide = function() {
var ajaxResponseArgs = arguments.callee.caller.arguments[2]; // accesses oncomplete arguments
if (ajaxResponseArgs && ajaxResponseArgs.validationFailed) {
return; // on validation error, prevent closing
}
this.originalHide();
};
});
This way, you can keep your code like:
<p:commandButton value="Save" oncomplete="videoDetalheDialogJS.hide();"
actionListener="#{videoBean.saveVideo(video)}" />
to keep the dialog Open on validation Failed, you just need set the commandButton as follows:
<p:commandButton value="save"
action="#{YourBean.yourActionMethod}"
oncomplete="if (!args.validationFailed) PF('yourDialogWidgetVar').hide()"/>
I gonna leave here a complete example:
<h:form id="ad-form">
<p:dialog id="ad-dialog" widgetVar="adDialog" modal="true" width="400"
closeOnEscape="true" resizable="false" header="Addreass">
<p:messages id="a-msgs" closable="true" />
<h:panelGrid columns="2" id="ad-painel-dialog" width="100%">
<p:outputLabel value="Country" for="country" />
<p:inputText id="country" style="width:100%"
value="#{clientSaverBean.editableAddress.country}" />
<p:outputLabel value="City" for="city" />
<p:inputText id="city"
value="#{clientSaverBean.editableAddress.city}" />
<p:outputLabel value="Zip-Code" for="zipcode" />
<p:inputText id="zipcode"
value="#{clientSaverBean.editableAddress.zipCode}" />
<p:outputLabel value="Street" for="street" />
<p:inputTextarea id="street"
value="#{clientSaverBean.editableAddress.street}" />
<p:outputLabel value="Number" for="number" />
<p:inputText id="number"
value="#{clientSaverBean.editableAddress.number}" />
<h:panelGroup />
<f:facet name="footer">
<p:commandButton value="save"
action="#{clientSaverBean.saveAddress}"
process=":ad-form:ad-dialog"
update=":ad-form:a-msgs :ad-form:ad-painel-dialog :client-form:ad-table"
oncomplete="if (!args.validationFailed) PF('adDialog').hide()"/>
</f:facet>
</h:panelGrid>
</p:dialog>
</h:form>

Ajax not working with primefaces

In my JSF page I have form when I click submit button in the same page I need to show an static content. But When I click <p:commandbutton> nothing appears in the page. When I put ajax="false" then only action taken place but the Static content display in new page.
In my Backing bean I have used Session scoped. I am using JSF 2.0 and Primefaces 3.2.
My JSF Page.
<h:form>
<h:panelGroup rendered="#{not license.showForm}">
<p:panel header="License Key Request" >
<h:panelGrid columns="2" >
..
<h:outputText value="Bla bla"/>
..
<h:outputText value="Bla Bla" />
</h:panelGrid>
<TABLE>
..
<h:outputLabel for="name" value="Requestor Name : *" />
..
<p:inputText id="name" value="#{license.name}" required="true" requiredMessage="Name is required."/>
..
<h:outputLabel for="company" value="Company : * " />
..
<p:inputText id="company" value="#{license.company}" required="true" requiredMessage="Company is required."/>
..
</table>
<p:commandButton value="Form" id="btnAdd" process="#form"
action="#{license.add}" />
..
</table>
</p:panel>
</h:panelGroup>
<h:panelGroup rendered="#{license.showForm}" >
<h:outputText value="Bla Bla"/>
</h:panelGroup>
</h:form>
Your source code is somewhat confusing (e.g. you have two closing table tags). But I assume that you want to show the panelGroup at the bottom if the button is clicked.
The easiest way would be to add an update ="#form" to your commandButton:
<p:commandButton value="Form" id="btnAdd"
process="#form" update="#form"
action="#{license.add}" />
You don't need to update the whole form but only the specific component. Then you need to give the panelGroup an id attribute and use this attribute instead of #form. However, since it is not clear for me how your naming containers are organized, it could be puzzling to find the correct relative id.

Resources