primefaces selectOneMenu ajax even on click not working - jsf

I am unable to get the ajax event click to work with primefaces selectOneMenu. Using the latest primefaces 11.0. The documentation states that these are available ajax events: blur, change, click, dblclick, focus, itemSelect, keydown, keypress, keyup, mousedown, mousemove, mouseout, mouseover, mouseup, select, valueChange.
<p:selectOneMenu value="#{beam.event}" editable="false" id="event">
<f:selectItems value="#{beam.events}"/>
<p:ajax event="click" onstart="console.log('start 1');" immediate="true" listener="#{beam.onClick}" update="#this"/>
<p:ajax event="click" onstart="console.log('start 2');" immediate="true" listener="#{beam.onClickNoParam}" update="#this"/>
</p:selectOneMenu>
The onstart client side callbacks are not triggered. The beam listeners look like this:
public void onClick(AjaxBehaviorEvent event) {
System.out.println("onClick");
}
public void onClickNoParam() {
System.out.println("onClick");
}
I did get the focus event to work, but it is triggered way to many times and unfortunately in combination with the the update one gets stuck in an endless recursive loop.
I don't notice any issues when the click event is registered by the AjaxBehaviorHandler/AjaxBehaviorListenerImpl compared to the focus event.

Related

jsf valuechangelistener not firing on checkbox deselect

I have a primefaces checkbox on a form with a valuechangelistener. The backing bean method gets called on checkbox select, but doesn't get called on deselect.
I'm using the same technique with almost identical code elsewhere in my application and it works fine on both select and deselect.
<p:selectBooleanCheckbox value="#{shareoutSlip.processed}"
valueChangeListener="#{orderFormBean.handleShareoutSlipProcessed}" >
<p:ajax />
</p:selectBooleanCheckbox>
Here is the valueChangeListener method (all it does for now is print a message to the console):
public void handleShareoutSlipProcessed(ValueChangeEvent vcEvent) {
logger.info("Shareout Slip Processed");
}
Is there anything else on my form that could be interfering with the method being called on checkbox deselect? I've put a h:messages tag on the form but I'm not seeing any validation messages.
Have you tried to call this method inside p:ajax tag?
<p:selectBooleanCheckbox value="#{shareoutSlip.processed}">
<p:ajax event="change" listener="#{orderFormBean.handleShareoutSlipProcessed}" />
</p:selectBooleanCheckbox>

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

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;
}

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.

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.

Listening to onSelect events from Autocomplete (Primefaces) component

I am trying to listen to select event from autocomplete using attribute selectListener.
I am passing a remoteCommand as select listener. But the selectListener never calls this remoteCommand method.
My code follows:
<h:form>
<p:autoComplete autocomplete="true" completeMethod="#{search.fetchSuggestions}" value="#{search.selectedSuggestion}" selectListener="moveToSelectedPage()"/>
<p:remoteCommand name="moveToSelectedPage" action="firstPage.xhtml?faces-redirect=true" />
</h:form>
All I am trying to do is, navigating to a different page after the user selects a particular suggested item among suggestions made by autocomplete.
Looking at PrimeFaces version 3.5, it appears that the selectListener attribute is no longer available for the AutoComplete component. The link in BalusC's answer leads to the correct place, where it shows the new approach to be to include a <p:ajax> tag inside the <p:autocomplete>:
<p:autoComplete id="acSimple" value="#{autoCompleteBean.txt1}" completeMethod="#{autoCompleteBean.complete}">
<p:ajax event="itemSelect" listener="#{autoCompleteBean.handleSelect}" update="messages" />
</p:autoComplete>
The selectListener attribute should refer to a managed bean method taking SelectEvent and returning void, not to some arbitrary JavaScript function.
See also the PrimeFaces <p:autoComplete> showcase page.
<p:autoComplete selectListener="#{autoCompleteBean.handleSelect}" ... />
with
public void handleSelect(SelectEvent event) {
// ...
}

Resources