Cursor caret always changing after AJAX request - ajax

I'm trying to keep a button on a JSF page disabled as long as all the input fields on the page are not entered.
The first thing I've tried is to use partial triggers on the button, with an EL expression on the "Disabled" property, and adding partial triggers on the button with the IDs of the input fields. To make this work I also set "AutoSubmit" to true on all the input fields.
<af:inputText label="First Name" id="fn_input" autoSubmit="true">
<f:validator validatorId="NameValidator"/>
</af:inputText>
<af:inputText label="Last Name" id="ln_input" autoSubmit="true">
<f:validator validatorId="NameValidator"/>
</af:inputText>
<af:button text="Submit" id="submit_btn" partialTriggers="fn_input ln_input" disabled="#{empty bindings.FirstName.inputValue or empty bindings.LastName.inputValue}"/>
This works, however, when both input fields are filled, the button only gets enabled when the user clicks outside of the field (or focuses out of it by pressing tab or clicking somewhere else).
So the second method I tried was to use an ajax call on the input field's "keyPress" event, and refreshing the button.
<af:inputText label="First Name" id="fn_input" autoSubmit="true">
<f:ajax render="submit_btn" event="keyPress" />
<f:validator validatorId="NameValidator"/>
</af:inputText>
<af:inputText label="Last Name" id="ln_input" autoSubmit="true">
<f:ajax render="submit_btn" event="keyPress" />
<f:validator validatorId="NameValidator"/>
</af:inputText>
<af:button text="Submit" id="submit_btn" disabled="#{empty bindings.FirstName.inputValue or empty bindings.LastName.inputValue}"/>
When using the above method, the required functionality is achieved, however, every time the user types a character in the field, the cursor goes back to the beginning of the field.
Using Chrome's inspection tools, I tracked the ajax call, and found out that the button is being refreshed as well as the button, thus resulting in resetting the cursor caret to the start of the word.
How do I solve this issue?
Note:
I am using release 12c.
The submit button and the input texts are not in the same panelFormLayout, because of design and layout requirements.
Thanks in advance.

Coming back to this question to post what eventually worked for me.
It was a bug with the 12.2.1.3 version of ADF. After upgrading to 12.2.1.4 the cursor caret stopped going back to the beginning of the inputs but the button would still stay disabled.
Replacing the ajax event from "keyPress" to "keyUp" did the trick.
<af:inputText label="First Name" id="fn_input" autoSubmit="true" value="#{bindings.FirstName.inputValue}">
<f:ajax render="submit_btn" event="keyUp" />
<f:validator validatorId="NameValidator"/>
</af:inputText>
<af:inputText label="Last Name" id="ln_input" autoSubmit="true" value="#{bindings.LastName.inputValue}">
<f:ajax render="submit_btn" event="keyUp" />
<f:validator validatorId="NameValidator"/>
</af:inputText>
<af:button text="Submit" id="submit_btn" disabled="#{empty bindings.FirstName.inputValue or empty bindings.LastName.inputValue}"/>

In Oracle ADF if you want to refresh a component and all it's attribute you need to add the PPR on it's parent component.
In your first case :
<af:panelFormLayout id="pfl1" partialTriggers="fn_input ln_input">
<af:inputText label="First Name" id="fn_input" autoSubmit="true">
<f:validator validatorId="NameValidator"/>
</af:inputText>
<af:inputText label="Last Name" id="ln_input" autoSubmit="true">
<f:validator validatorId="NameValidator"/>
</af:inputText>
<af:button text="Submit" id="submit_btn" disabled="#{empty bindings.FirstName.inputValue or empty bindings.LastName.inputValue}"/>
</af:panelFormLayout>

Related

Validate two components with dynamic id

Here is what I am trying to do:
I have a form with multiple pairs of input fields and a save button.
When the save button is pressed then for each pair of input fields should be validated if they are numbers and if the left value is smaller than the right value.
If not the validation errors will be shown and if it is the case a dialog will pop up to ask for the name under which it should be saved.
Here is what I got so far:
<h:form>
<ui:repeat value="#{myBean.someList}" var="elem">
<h:inputText id="min#{elem.id}" value="#{elem.minimum}" />
<h:inputText id="max#{elem.id}" value="#{elem.maximum}" />
<br />
<h:message for="min#{elem.id}" style="color:red" />
<h:message for="max#{elem.id}" style="color:red" />
</ui:repeat>
<h:commandButton value="save">
<f:ajax execute="#form" render="#form updateValidationFailedFlag"
onevent="
function(ajaxResult){
if(ajaxResult.status=='success' && !globalValidationFailedFlag)
showSaveDialog();
}"
/>
</h:commandButton>
<h:outputScript id="updateValidationFailedFlag">
globalValidationFailedFlag = #{facesContext.validationFailed};
</h:outputScript>
</h:form>
This works but doesn't check if the minimum is smaller then the maximum.
It will validate the input (checks if the input are integer) and shows the save dialog if no validation error occured.
To check if the minimum is smaller then the maximum I tried to follow the tutorial at http://www.mkyong.com/jsf2/multi-components-validator-in-jsf-2-0/
Variant 1 adds a listener after the validation is done and is able to add error messages that are shown in the browser. But that doesn't count as a validation failure and doen't set the facesContext.validationFailed flag.
Variant 2 writes a custom validator for one component and gives the other component as parameter to that validator. That would look something like this:
<f:validator validatorId="myValidator" />
<f:attribute name="maximum" value="#{max#{elem.id}}" />
That is not really valid EL and I don't know how to write it correctly.
What can I do to validate if each of those min-max pairs is valid
You don't need #{elem.id} here. The <ui:repeat> already takes care of that. It would be evaluated to an empty string anyway when JSF needs to set the id attribute.
<ui:repeat value="#{myBean.someList}" var="elem">
<h:inputText id="min" value="#{elem.minimum}" />
<h:inputText id="max" value="#{elem.maximum}" />
<br />
<h:message for="min" style="color:red" />
<h:message for="max" style="color:red" />
</ui:repeat>
As to the validation, just pass the value of the other component along:
<h:inputText id="min" binding="#{min}" value="#{elem.minimum}" />
<h:inputText id="max" value="#{elem.maximum}">
<f:validator validatorId="myValidator" />
<f:attribute name="min" value="#{min.value}" />
</h:inputText>
Note that I moved the validator to the second component. Otherwise it would be still invoked if the second component didn't pass conversion.
If you happen to use JSF utility library OmniFaces, then you could use its <o:validateOrder> instead.
<h:inputText id="min" value="#{elem.minimum}" />
<h:inputText id="max" value="#{elem.maximum}" />
<o:validateOrder components="min max" showMessageFor="min" />
See also:
How to use EL with <ui:repeat var> in id attribute of a JSF component
JSF doesn't support cross-field validation, is there a workaround?

Show previous valid value of h:selectOneListbox when invalid selection is made

I have a problem with the validation of a selectOneListBox. Everything works fine and a message is displayed, when the input is false. But the dropdown keeps the selected value as the dropdown value. I want to display the old value if validation fails.
So how can I do that?
I tried this:
<h:selectOneListbox id="intFrom" value="#{searchBean.intFrom}" size="1" immediate="true" class="intSelectBox1">
<f:ajax render=":menuForm :searchForm:searchButton" listener="#{menuBean.focus(menuBean.mySearch)}" />
<f:ajax listener="#{searchBean.count()}" render="int1" />
<f:ajax execute="intFrom" render="intFrom" />
<f:selectItems value="#{searchBean.intRangeFrom}" />
<f:validator validatorId="project.IntFromValidator" />
</h:selectOneListbox>
<h:message id="int1" for="intFrom" style="color: red" />
But after that the new value is being displayed not the old one.

Composite Component - AJAX clientBehaviour

We have build a component that consists of a TextInput and Select Box. So that the selection can be made either via the drop down list or by typing in the value into the text field. When a selection is made the Input Box is automatically filled with the key and if the key is entered the correct item in the selection box is displayed.
<h:panelGroup rendered="#{cc.attrs.rendered}">
<div id="#{cc.clientId}" class="abc-select #{cc.attrs.styleClass}" >
<h:inputText id="input" disabled="#{cc.attrs.disabled}"
value="#{cc.attrs.value}">
<a4j:ajax event="change" render="select" />
</h:inputText>
<rich:select disabled="#{cc.attrs.disabled}"
id="select" value="#{cc.attrs.value}"
listWidth="#{cc.attrs.listWidth}"
converter="#{cc.attrs.converter}">
<f:selectItems value="#{cc.attrs.items}" var="item"
itemValue="#{item}" itemLabel="#{item.name}" />
<a4j:ajax event="selectitem" render="input" oncomplete="setFocusOnInputField();" />
</rich:select>
</div>
</h:panelGroup>
However when we pass in an <a4j:ajax event="change" ... /> with an onChange event to render a component external element. It only works when the selection is made via the drop down menu.
<abc:myComponent id="idMC"
value="#{bean.value}"
items="#{bean.itemList}"
converter="#{itemConverter}">
<a4j:ajax event="change" render="idA idB idC" />
</kfn:select>
So far I figured out that it must have to do with the fact that the inputText already has an a4j element listing for change <a4j:ajax event="change" render="select" />.
When I change the ajax element in the inputText element to use <f:ajax .. /> instead it works fine.
Can someone explain why this is the case and is there a better solution?

Refresh a form skipping validation when press a button for close: jsf+richfaces

I am using JSF and richfaces. And I am new.
I am looking for information about reset a form in a popup after close it, I do not need to validate the form neither render it. I want to close it and then when I open it again I want the form to be clean.
I have looked information about this, however I do not find the answer to my case. What I have is :
<rich:popupPanel ....
<a4j:outputPanel id="editPaneRegion">
<h:form id="form2EditPane">
<h:panelGrid columns="2" id="edit" ...>
<rich:validator>
<h:outputLabel for="nameContact" value="... " />
<h:panelGrid>
<h:inputText id="nameVontact" value="xbean.selected.name" label="..." required="true" size="20" tabindex="1">
<f:validator validatorId="personNameValidator" />
</h:inputText>
<rich:message for="nameContact" ajaxRendered="true"/>
</h:panelGrid>
</rich:validator>
</h:panelGrid>
....
<a4j:commandButton id="update" value="..." action="#{xBean.edit}" render="form1EditPane:tableContacts, form1EditPane:contactSelect" execute="editPaneRegion" tabindex="6"/>
...
<a4j:commandButton id="close" value="..." oncomplete="#{rich:component('editPane')}.hide();return false;" execute="#this" ajaxSingle="true" immediate="true" tabindex="7"/>
The close button does not works as should be. If I oppen the popup, edit the inputtext and then I close the popup, when I oppen the popup again, it is edited the inputtext, however I want the original as it should be without the edition.
I have found the same question but anything solves my case : I have tried, using a4j:region, different combination of attributes for the button: inmediate= true, action={...clean}, ajaxSimple=true, .. however it doesn't work.
Have someone a solution for this case, I think I miss something obvious as this behaviour should be a common thing, though.
You just need to rerender the form. Whatever you use to make the popup appear make it render the popup as well:
<a4j:commandLink …
render="popupPanel" oncomplete="#{rich:component('popupPanel')}.show();" />
And do not nest forms, you don't have to wrap inputboxes into a <form> like you do in HTML.

RichFaces: partial form validation

I have a form containing several fields(name, surname, etc) and a datatable. Datatable is dedicated to store addresses into the backing bean. A person can have more than one address so I add a button as follows:
<a4j:commandButton action="#{bean.addAddressRow}" value="Add address" reRender="addresses" />
where "addresses" is the id of my datatable. I use a4j because there's no need to refresh the page.z
What I want to do is to skip the validation of the entire form except the address fields when this button is pressed. So a user can add one more address if all the previous addresses are correctly filled. The other fields should not be validated.
Is it possible to do?
Wrap your address table and the commandButton with <a4j:region> tags and set the attribute renderRegionOnly to true. Look at following example. Here only the last two text boxes (txt2 and txt3) are validated when you press the first button. If you press the second button all three text boxes are validated.
<h:form>
<h:inputText required="true" id="txt1"/>
<rich:message for="txt1" style="color:red"/>
<a4j:region renderRegionOnly="true">
<h:inputText required="true" id="txt2"/>
<rich:message for="txt2" style="color:red"/>
<h:inputText required="true" id="txt3"/>
<rich:message for="txt3" style="color:red"/>
<a4j:commandButton value="Ok1" />
</a4j:region>
<a4j:commandButton value="Ok2" />
</h:form>

Resources