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

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>

Related

Update p:inputText style while typing

How do I update the style of a p:inputText while the user is typing without interrupting their typing?
<p:inputText id="radiusValue" value="#{bean.radius}"
styleClass="#{bean.radiusStyle}">
<p:ajax event="keyup" update="radiusValue" />
</p:inputText>
This is for validation. It updates fine and gets the correct style but when the p:inputText updates, it sets the cursor back to the beginning... interrupting the user's entry. There has to be a less invasive way to update the style?
Could you do that validation on client?
I have not tried, but you can use onkeyup attribute to execute a Javascript function that adds a style class depending on what do you need.
function applyStyle() {
var element = document.getElementById("myInputText");
element.classList.add("mystyle");
}

<p:autoComplete> losing values during input

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?

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>

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.

JSF f:ajax does not render immediately

I have a input text like this:
<h:inputText value="#{someValue}">
<f:ajax event="change" listener="#{someMethod}" render="someDataTable"/>
</h:inputText>
I have a data table like this:
<h:dataTable value="#{someList}" var="anyVar" id="someDataTable">
some things
</h:dataTable>
When I change the text in the input text, the change is not hapenning immediately, rather I have to click on the page on anything to get the required result in the data table.
Does anyone know how to solve this problem?
On HTML input text elements, the HTML DOM change event is only fired when the element's value has been changed and the element loses focus (i.e. the blur event has been fired as well). Clicking anywhere else on the page or tabbing to next element would fire the blur event. So the described symptoms perfectly matches the specified behaviour.
You're most probably interested in the keyup event.
<f:ajax event="keyup" ... />
Keep in mind that this fires the Ajax request on every keystroke which is not necessarily cheap. You might want to add a delay of ~200ms.
<f:ajax event="keyup" delay="200" ... />
See also:
What values can I pass to the event attribute of the f:ajax tag?

Resources