PrimeFaces p:ajax event=change and p:commandButton action - jsf

I am having some trouble with my application. I have a <p:inputText> with a <p:ajax> listener for the change event. I also have a <p:commandButton> on my page. Both the ajax listener and <p:commandButton> work as expected when only attempting to invoke one. The problem occurs when user edits <p:inputText> and while still focused on the field, attempts to press the <p:commandButton> which triggers the change event ajax listener (expected) but the <p:commandButton> is not invoked (not expected).
Here is my code:
<p:inputText id="code"
value="#{myBean.code}" >
<p:ajax event="change"
listener="#{myBean.method1(myBean.code)}"
update="#(form :input:not(button))" />
</p:inputText>
<p:commandButton id="searchButton"
value="Click me"
action="#{myBean.method2(myBean.code)}"
process="#this code"
update="#form"
oncomplete="PF('myDlg').show()" />
I have read this question but the answer didn't seem to solve the issue for me.
I have tried processing the button on the ajax listener and I tried putting the button in a different form and not updating that form from the ajax listener but I can't figure it out. Is what I am trying to do even possible?
Thanks in advance for any help.

If your project is running on JSF 2.2 runtime, you can utilize passthrough attributes from namespace http://xmlns.jcp.org/jsf/passthrough
I had the same issue (button doesnt work on 1st press, on next presses it works) and solved it on following way:
Add namespace to your page
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
Add oninput attribute to p:inputText (no need for p:ajax)
<p:inputText id="code" value="#{myBean.code}" pt:oninput="onTextChanged()"/>
Add p:remoteCommand bellow
<p:remoteCommand delay="300" name="onTextChanged"
actionListener="#{myBean.method1(myBean.code)}"
update="#(form :input:not(button))" />
(Delay is not necessary but it gives better performance if text is typed fast.)
oninput attribute will help your input fields to detect any kind of change event: typing, deleting, copying, pasting, cutting,etc... and via p:remoteCommand to pass them to managed bean.
And you will also solve "button" issue.

Sorry for my english.
I found another workaround for this issue.
Advantage against approved answer - no additional requests to server on user input.
I realized that the problem is that the button onclick handler is not called.
But I noticed that the onmousedown handler is called. So I added an onmousedown handler where I shedule onclick call. In the onclick handler I check if the method has already been called or not. And if it was, I cancel the event. So onclick executes only one time for one button click.
Page markup:
<p:commandButton id="searchButton"
...
onclick="return fixOnclick(event)"
onmousedown="return fixOnmousedown(event)"
</p:commandButton>
Javascript:
fixOnmousedown: function (e) {
const target = $(e.target);
target.data("eventToProcess", null);
setTimeout(function () {
target.trigger("click");
}, 10);
return true;
}
fixOnclick: function (e) {
const target = $(e.target);
if (target.data("eventToProcess") == null) {
target.data("eventToProcess", e);
}
return target.data("eventToProcess") === e;
}

Related

Add exception in Primefaces ajaxStatus to allow rowDblselect event on datatable

I have a datatable that has both a rowSelect ajax event (for selecting a row and showing some extra information on some bottom panels) and a rowDblselect ajax event (for opening that record in an edit window).
<p:ajax event="rowSelect" listener="#{myBean.onSagRowSelect}" update=":bottomPanel" />
<p:ajax event="rowDblselect" listener="#{myBean.onSagRowDblClick}" update=":content" onstart="startWait();" oncomplete="stopWait();"/>
This worked fine until we added an ajaxStatus component that is meant to show a loading bar gif when an ajax call is made, to let the user know that something is happening in the page. The problem is that this ajaxSTatus component is blocking my rowDblselect event, now it will only trigger rowSelect event, even if I double click a row.
<p:ajaxStatus onstart="PF('loadingDialog').show()" onsuccess="PF('loadingDialog').hide()" />
<p:dialog widgetVar="loadingDialog" modal="true" draggable="false" closable="false" resizable="false" showHeader="false">
<p:graphicImage name="../images/ajaxloadingbar.gif" />
</p:dialog>
We're using Primefaces 5.2.
Is there any way I can configure the ajaxStatus to delay the onstart or something similar so that it allows my double click event to complete?
Any help/advice on this matter is welcomed. Thank you!
I haven't tried that myself, but I think you could delay displaying the dialog for all events using JavaScript setTimeout, like this:
<p:ajaxStatus onstart="setTimeout(function() { PF('loadingDialog').show(); }, 500);"
onsuccess="PF('loadingDialog').hide()" />
Other option would be to set global="false" to the p:ajax for rowSelect only - it should stop triggering ajaxStatus for this particular event. You would then have to define onstart attribute to show the dialog with delay (as shown above) and oncomplete to hide it again:
<p:ajax event="rowSelect" listener="#{myBean.onSagRowSelect}" update=":bottomPanel"
global="false"
onstart="setTimeout(function() { PF('loadingDialog').show(); }, 500);"
oncomplete="PF('loadingDialog').hide();" />
By the way, I think you should really use oncomplete instead of onsuccess in this case since in case the ajax request fails for some reason, the dialog may stay displayed, blocking your application due to its modality.

How to redirect to a page after printing with primefaces Printer?

I have used the primefaces printer and wanted to redirect to previous page after printing.I used Printer like this:
<p:commandButton value="Print" type="button" title="Print" actionListener="#{currentpage.redirect}">
<f:ajax execute="#this"/>
<p:printer target="printer" />
</p:commandButton>
In redirect method of currentpage bean i deleted the record which works fine but if i try to redirect it to previous page it doesn't do anything.
public void redirect(ActionEvent actionevent) {
/* Deleted the record */
}
Please guide me if i can do this way or anyother way.
Thanks in advance.
There are several misconceptions in your code:
actionListener method can not fire a redirect. That could be done in action
An ajax request cannot fire a redirect. Ajax is meant to work as an asynchronous request to the server and get the desired result to the current view and handle the response to update the view without refreshing the page nor without navigating.
If using Primefaces components, you should work with them for efficiency in your page. For example, <p:commandButton> should work with <p:ajax> rather than <f:ajax>. But in this case, <p:commandButton> already has ajax capabilities built-in, so there's no need to use any of these ajax components.
After knowing this, you know that your design should change to this:
<p:commandButton value="Print" type="button" title="Print"
action="#{currentpage.redirect}" process="#this">
<p:printer target="printer" />
</p:commandButton>
And the method declaration to:
//parameterless
public void redirect() {
/* Deleted the record */
}
PrimeFaces let's you add behavior when the ajax request is complete by usage of oncomplete attribute. This attribute receives the name of a javascript function that will be invoked right when the ajax request finishes without problems. In this method, you can add the logic for your redirection:
<p:commandButton value="Print" type="button" title="Print"
action="#{currentpage.redirect}" process="#this" oncomplete="redirect()">
<p:printer target="printer" />
</p:commandButton>
<script type="text/javascript>
redirect = function() {
window.location.href = '<desired url>';
}
</script>

PrimeFaces autocomplete: itemSelect versus change events

I need to trigger an ajax update upon change to a text box, which is a <p:autoComplete> component. I have observed that if the user opts to type the text manually, the event is a change, whereas if the user clicks one of the suggestions for the autocomplete, the event is itemSelect. So I added two <p:ajax> children to the input, each calling the same method and having the same update list, but one having event="change" and the other event="itemSelect".
However, I now discover something odd. For example, while in normal server mode I opened my page and typed "12". The autocomplete offered "1233" and "1234" as suggestions. I clicked "1233" and seemingly nothing happened. I clicked again and everything else filled in.
Repeat this in the debugger with a breakpoint on the event handler, and I can see that after the first click, the value is "12" and on the second click, it becomes "1233".
By switching commenting out the two different <p:ajax> I can see the different consequences. Without the "change" one, the handler is never called if the user selects an autocomplete suggestion, and without the "itemSelect" one, the handler is never called if the user types manually. But with both of them, there are two calls, and I'm sure there will be complaints about the double-click.
Some pseudo-code for those that like, first the xhtml:
<p:autoComplete id="itemId" value="#{myBacker.myBean.itemNumber}"
required="true" completeMethod="#{myBacker.idAutoComplete}">
<p:ajax event="itemSelect" update="beanDetails"
listener="#{myBacker.idChangeEventListener()}" />
<p:ajax event="change" update="beanDetails"
listener="#{myBacker.idChangeEventListener()}" />
</p:autoComplete>
<h:panelGroup id="beanDetails">
<h:panelGroup rendered="#{not empty myBacker.myBean.institutionName}">
<h:outputText value="#{myBacker.myBean.institutionName}" />
<!-- Continues with address, phone, etc.. -->
</h:panelGroup>
</h:panelGroup>
Then the Java backing bean code:
public void idChangeEventListener() {
myBean = myDAO.getDetails(myBean);
// another couple of init-type method calls
}
Give the parent tag a widgetVar attribute, then add this little attribute to the <p:ajax event="change" ...> child tag:
onstart="if(widgetVarName.panel.is(':visible')) return false;"
When the question was written, we were on PrimeFaces version 3.5, if I recall correctly. Since then, we need to update the solution to:
onstart="if(PF('widgetVarName').panel.is(':visible')) return false;"
with thanks to mwalter for pointing out the change.

PrimeFaces dialog validation errors

What i want to do is like basic row selection example at Primefaces showcase(http://www.primefaces.org/showcase/ui/datatableRowSelectionByColumn.jsf) I want to update my datatable's row. The problem is when i click to update button at datatable, dialogbox appears with validation errors.
Second thing is what is the order of method execution times.(action-update-onclick-f:setPropertyActionListener)
<p:commandButton id="updateButtonId"
action="#{myController.showCompanyEditPanel}"
update=":tabView:companyForm:companyEditPanel"
onclick="companyDialog.show()"
icon="ui-icon-pencil" title="update">
<f:setPropertyActionListener value="#{company}" target="#{myController.selectedCompany}" />
</p:commandButton>
<p:dialog id="editCompanyDialogId" header="CompanyEdit" widgetVar="companyDialog" resizable="false">
<p:panel id="companyEditPanel" >
//some stuff here
</p:panel>
</p:dialog>
You seem to be missing a major point of using a <p:commandButton> here, as well as seem to be mixing client-side and server-side events.
First on <p:commandButton>. This component is designed to POST (partial) form data to the current URL, do business job in action(listener) method and return updated components / perform navigation. You can of course 'attach' JavaScript events to all those attributes.
Second, onclick, oncomplete, and other on... attribute are corresponding to some client-side events. In particular, onclick function is triggered when button was clicked, oncomplete function is called when DOM was updated after the AJAX call, i.e. the elements specified in <p:ajax update="..."> or simply in update="..." attribute of <p:commandButton>.
Third, all action listeners (thus, actionListener attribute, <f:actionListener> tag, <f:setPropertyActionListener> tag) will be executed right in the order they are specified in your tag, see this answer for more elaboration. The last one to be executed is action method, after which response is sent back.

f:ajax listener not called for h:selectBooleanCheckbox

With code like this :
<h:selectBooleanCheckbox value="#{user.data['selected']}">
<f:ajax event="click" listener="#{timetableBean.processUserEvents}" />
<f:attribute name="user" value="#{user}" />
</h:selectBooleanCheckbox>
The method code is :
public void processUserEvents(AjaxBehaviorEvent e) {
User user = (User) e.getComponent().getAttributes().get("user");
...
}
Clicking on the checkbox does trigger the ajax submit, but the listener method is not being called at all.
To top it off, there's no error messages, and the phases complete normally.
Im was trying mojarra 2.0.4-b09, and after facing this error, i changed to 2.1.2, but the same problem persists.
Is there anything i did wrong ?
Thank you.
UPDATE
The problem was placing the h:selectBooleanCheckbox inside the primefaces datalist (p:dataList). Placing it outside works fine. I wonder what the problem is. Will ask in the primefaces forum now.
Here lies the answer of a similar problem.
The problem was really putting the checkbox inside p:dataList without encapsulating it in a p:column.
After wrapping it with p:column, the listener will be called normally.
Hope it helps !

Resources