<p:autoComplete> losing values during input - jsf

I'm using p:autoComplete of Primefaces with following setup:
<p:autoComplete
id="Nr"
dropdown="true"
autoHighlight="false"
scrollHeight="300"
value="#{View.Nr}"
completeMethod="#{view.completeNr}">
<p:ajax
event="change"
update="nrStatus" />
<p:ajax
event="itemSelect"
listener="#{view.onNrSelect}"
update="nrStatus" />
</p:autoComplete>
when user input needs longer than 300ms, p:autoComplete fires ajax-change-event. If user adds input during the fired change-event, the inputfield doesnt get the new input. I assume that, during change-event, the inputfield of p:autoComplete loses its focus.
what I want:
first: no more lost inputs
second: fire new change event, if value of input changed since first change event.
temporary solution: increased "queryDelay"-attribute to 1000ms
my question: is there any possibility to realize this?

Related

Trigger valueChange event after a visible character is added or removed in InputText

I am in need for a valueChange event, that triggers every time a visible character is added or removed.
I've got 2 inputText-fields, one of which is read only and a commandButton.
<div>
<p:inputText>
<p:ajax id="encodedString" event="valueChange"/>
</p:inputText>
<p:commandButton action="#{bean.foo}" update="output"/>
<p:inputText id="output" readonly="true">
</p:inputText>
</div>
Now, the users enters some encoded string in the first field and presses the button, which then decodes the string and presents it in human readable form in the read-only input field. Now, whenever the user manipulates the original string, the output should be reset since it does not represent the original encoded string anymore.
Sadly, the valueChange event only triggers when the input field loses focus. I have tried the keypress event, but it also triggers when buttons like the arrow keys are pressed.
JavaScript is viable for me, but should be omitted if possible.
What is the best way to trigger the valueChange event (or a similar event) whenever the actual input changes? I.e. when a visible character is added or removed.
You essentially need the HTML DOM input event. This relatively new event is unfortunately not supported in <p:ajax> of <p:inputText> because the oninput attribute is not supported in <p:inputText> (yet?).
However, you can make use of JSF 2.2's passthrough attributes feature to force JSF to render an oninput attribute anyway where you in turn explicitly trigger the default onchange() function.
<... xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
<p:inputText value="#{bean.value}" a:oninput="onchange()">
<p:ajax listener="#{bean.listener}" />
</p:inputText>
True, that involves JavaScript but it's really only a small bit.
Note that I removed event="valueChange" from <p:ajax> because that's the default one already.
value changed event not supported for inputText you have to use
keyup or blur
<p:inputText>
<p:ajax id="encodedString" event="keyup"/>
</p:inputText>

Primefaces: Keep value of input text inside a dialog after calling initPosition

I have a dialog which need to be rerender after a certain selectOneMenu ist chosen.
To accomplish that, the following code is used inside the selectOneMenu:
<p:ajax event="valueChange" oncomplete="PF('dialog').initPosition();" update="panelGrid" />
However, after the dialog is rerendered, all user inputs in my p:inputTextare lost (reset to value from java bean).
How can I make the inputText keep the new value without persisting it to backend?
provide the XHTML page where your inputText component is situated. My best guess to solve your problem is by adding the p:ajax component inside the inputText component. p:ajax as defined below triggers on the default event which is change and processes #this which is the inputText component. this way it saves your input on the backing bean as soon as you exit the field.
<p:inputText value="#{bean.value}" >
<p:ajax />
</p:inputText>

How to reset input components on change of <p:selectOneMenu> after certain validations are violated

I'm populating <p:selectOneMenu> from a database which contains a list of zones, when a JSF page loaded.
When a zone in this menu is selected, a set of <p:inputText> is displayed in which a user can insert charge that corresponds to product weight which is to be transferred by a transporter to the selected zone in the menu. This can be shown in the following snap shot.
As can be seen, when non numeric values are entered by a user, validation violations occurs, when the given save button <p:commandButton> is pressed (the numbers displayed on top of each text field correspond to weight).
If a user now change the zone in the menu - the first panel without pressing the reset button, the data corresponds to that newly selected zone is loaded in these text fields only when the reset button is pressed as follows (because of validation violation)..
So, how to load data after previous validation violation, if an item (zone) is changed in the menu?
The change event of <p:selectOneMenu>, in this case should do the function something like which is done by <p:resetInput>.
Hope you will be able to understand what I mean :).
Basically, you need the functionality provided by <p:resetInput> inside <p:ajax> of a <p:selectOneMenu>. This is indeed not possible as <p:resetInput> requires being placed in a component implementing ActionSource such as UICommand components.
Your best bet is to let <p:remoteCommand> take over the <p:ajax> change listener job. Therein you can put a <p:resetInput>.
Imagine that you currently have a:
<h:form>
<p:selectOneMenu id="zone">
<f:selectItems ... />
<p:ajax listener="#{bean.changeZone}" update="data" />
</p:selectOneMenu>
<p:panel id="data">
...
</p:panel>
</h:form>
Then this change should do:
<h:form>
<p:selectOneMenu id="zone" onchange="changeZone()">
<f:selectItems ... />
</p:selectOneMenu>
<p:remoteCommand name="changeZone" process="#this zone" action="#{bean.changeZone}" update="data">
<p:resetInput target="data" />
</p:remoteCommand>
<p:panel id="data">
...
</p:panel>
</h:form>
Don't forget to remove the AjaxBehaviorEvent argument from the listener method. It's useless in this particular case anyway.

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.

Update form from value change of Primefaces spinner

I am trying to update my form on the basis of changes of the spinner
<p:spinner id="spin1" min="1" max="#{editPhoto.max}" size="1"
value="#{editPhoto.page}" validator="#{editPhoto.validator()}"
valueChangeListener="#{editPhoto.refreshForm()}" />
<p:commandButton value="Insert" action="#{editPhoto.insertImage()}" />
<p:commandButton value="Delete" action="#{editPhoto.deleteImage()}" />
I've put break points in the value, setPage as well as in the validator and valueChangeListener and it hits them only when I press the commandButton. I've tried immediate="true", but that adds nothing. What I really want is to know when the value has been changed, but without having to hit the commandButton.
In a previous question BalusC suggested the use of
<f:event type="preRenderView" listener="#{nextpageBacking.onPreRenderView}" />
I suspect that I need something similar here, but what sort of event should I be looking for? Maybe not, so what do I need to do to get changes in the spinner without having to press on the commandButton? Thanks, Ilan
My bean is view-scoped. Perhaps the answer is to use another request scoped-bean and have the request scoped-bean operate on the view-scoped bean? I will try this if this looks like the correct direction.
You should use f:ajax or p:ajax.
The valueChangeListener will only fire when the whole form or the spinner is submitted.
<p:spinner id="spin1" min="1" max="#{editPhoto.max}" size="1"
value="#{editPhoto.page}" validator="#{editPhoto.validator()}">
<p:ajax listener="#{editPhoto.refreshForm()}"
update="#form" process="#this" />
</p:spinner>
The valueChangeListener attribute of the spinner is not the best place to fire your method. You should better put it in the listener attribute of p:ajax. The valueChangeListener should be used if you are interested in the old and the new value.

Resources