Block a4j:support call when the input value is empty - java

Here is my code:
<h:inputText size="22"
value="#{bean.searchString}"
id="drugName">
<a4j:support
actionListener="#{bean.searchMedication}"
ajaxSingle="true" reRender="contentListGrid"
event="onkeyup" id="searchAjax"
requestDelay="200"
rendered="#{bean.searchString.length() > 0}">
</a4j:support>
</h:inputText>
I would like to prevent the a4j:support call whenever the input field is not filled out. I tried it by determining the input value length in the rendered attribute. However, it results in the following exception:
org.apache.jasper.JasperException: /pages/medication/MedicationList.jsp(147,9) The function length must be used with a prefix when a default namespace is not specified
at org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:40)
at org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:407)
at org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:148)
at org.apache.jasper.compiler.Validator$ValidateVisitor$1FVVisitor.visit(Validator.java:1478)
What does this message mean?
The function length must be used with a prefix when a default namespace is not specified
Can't we invoke a method in EL?

As to the concrete exception, invoking non-property methods (i.e. non-getter/setter methods) is only supported since EL 2.2 which is part of Servlet 3.0 / JSP 2.2. You seem to be using old JSF 1.x and thus also old Servlet 2.5 / JSP 2.1. Basically you end up with an EL syntax error.
Actually, you don't need EL 2.2 for this. Just use empty keyword instead.
rendered="#{not empty bean.searchString}"
However this approach won't work as well. The rendered attribute will be examined in the server side when the HTML code is to be generated and sent to the browser, not during the client side events as you seem to expect (rightclick page in browser, View Source, do you see any JSF code?). You need to use JavaScript to check the input value length in the onkeyup of the field or onsubmit of the Ajax call and return false accordingly.
<h:inputText ... onkeyup="return (!!value)">
or (not guaranteed that this works, I don't know off top of head what markup it generates)
<h:inputText ...>
<a4j:support ... onsubmit="return (!!value)" />
</h:inputText>
The first ! converts it to inversed boolean and the second ! re-inverses it. This way you end up with a fullworthy boolean return outcome depending on the presence of any value. If it's false, then the remaining onkeyup functions (such as you've specified with <a4j:support>) will be blocked.

Read BalusC answer.
You can do that also on client side, by first checking if the value is empty or not:
<h:inputText value="#{bean.searchString}" id="drugName">
<a4j:support onsubmit="if ($F('theFormID:drugName') == '') { return false; }"
.../>
</h:inputText>
($F('someId') is equivalent to document.getElementById('someId').value, with Prototype JavaScript library, which is included in Richfaces).

Related

In Primefaces inputText required=true, how can I remove ui-state-error as soon as something is entered?

When submitting a form that includes a required inputText, the styles that indicate not validated fields remain in place until submitting again. I want the styles to disappear as soon as the field is edited.
<p:inputText value="#{data.bezeichnung}"
id="bezeichnung"
styleClass="panelInputField input_mandatory"
required="true"
title="Bezeichnung"/>
After a lot of trying around, I found the easiest answer to add a "onkeyup" as follows:
<p:inputText value="#{data.bezeichnung}" id="bezeichnung"
styleClass="panelInputField input_mandatory"
required="true"
onkeyup="$(this).removeClass('ui-state-error');"
title="Bezeichnung"/>
If the jquery code needs to be in a more general place, the following might work as well: (it may be helpful to know the escaping codes used here)
onfocus="$('.ui-state-error').removeClass('ui-state-error');"
onkeyup="$('input[name="form:bezeichnung"]').removeClass('ui-state-error');"
onkeyup="$('input[name$=bezeichnung]').removeClass('ui-state-error');"

Why is this invalid EL expression?

I'm doing a simple logout and want to make sure i'm referencing correctly to the login root.
<h:form>
<h:commandLink value="Logout" action="#{request.contextPath}/#{userController.logout()}" />
</h:form>
but i get this error:
/topnav.xhtml #16,104 action="#{request.contextPath}/#{userController.logout()}" Not a Valid Method Expression: #{request.contextPath}/#{userController.logout()}
UPDATE
Right now I'm adding navigation rules from the logout link to the login page and since the logout link is on all pages i need to add rules to allow the transition back to the login page. that seems like a lot of configuration for a simple item. would prefer to just have the method called indicate that the login page the the final destination and hot have to place a navigation entry from all pages to the login page.
From the documentation for commandLink:
Name Required Request-time Type
==============================================================
action false false javax.el.MethodExpression
The composite expression #{request.contextPath}/#{userController.logout()} cannot be resolved as a MethodExpression.
The JSF 2.1 specification says of MethodExpressions:
Method expressions are a very similar to value expressions, but rather
than supporting the dynamic retrieval and setting of properties,
method expressions support the invocation (i.e. execution) of an
arbitrary public method of an arbitrary object, passing a specified
set of parameters, and returning the result from the called method (if
any).
try
<h:form>
<h:commandLink value="Logout" action="#{userController.logout()}" />
</h:form>
beside the fact that you do not need context, you can not use # twice the way you are using it.

Avoid validating/ submitting p:selectOneListbox's value completely

I'm fetching selectItems list for a p:selectOneListbox via ajax using a request scoped bean. Thus on submitting back the form I'm getting this error:
j_idt153:j_idt159:j_idt184:j_idt194: Validation Error: Value is not valid
I dont want to submit the value of p:selectOneListbox to any bean property that's why the value EL for that component was omitted but still JSF is validating the selected option & it is not there since my bean was request scoped. Now I want to completely skip validating this component since this p:selectOneListbox is just for presentation purposes & its value is not used after the submit form process. How do I avoid validating/ submitting p:selectOneListbox's value completely
<p:ajax event=".." listener="#{pim.retrieveProjects()}" update="usrProjctsList" />
<p:selectOneListbox id="usrProjctsList" onchange="jsfElmnt('#{cc.clientId}:selUsrProjct').val($(this).val());">
<f:selectItems value="#{pim.projects}" var="project" itemLabel="#{project.title}" itemValue="#{project.id}"/>
</p:selectOneListbox>
<h:inputHidden id="selUsrProjct" value="#{bean.underProject}"/>
I don't think that the error j_idt153:j_idt159:j_idt184:j_idt194: Validation Error: Value is not valid referring to <p:selectOneListbox id="usrProjctsList" cause its id not present in the j_idt153:j_idt159:j_idt184:j_idt194 id at all...
do view source in your browser and look for the j_idt153:j_idt159:j_idt184:j_idt194 id and try to find out to whom it belongs
also you can try to add immediate="true" to your <p:ajax to skip validation or try adding <p:ajax to that troublesome component j_idt153:j_idt159:j_idt184:j_idt194
As Daniel said, the id doesn't match either. But for skipping the validation you could also use the process=#this (and other stuff, except the listBox) on your ajax event. Since you are using primefaces this will just process the stuff written there and skip the rest.

f:param with condition

I have f:param like below...
<f:param name="NDCID" value="#{selectedMedicationInfoBean.NDCID}"></f:param>
<f:param name="insuranceID" value="#{selectedMedicationInfoBean.insurance.id}"></f:param>
in few cases
#{selectedMedicationInfoBean.insurance.id}
comes null. Can we prevent it? I can't use turnery operator inside JSF Expression.
<f:param name="insuranceID" value="#{selectedMedicationInfoBean.insurance.id=null?'':selectedMedicationInfoBean.insurance.id}">
Is there any other way?
Functional Requirement : On page1 there is a link of detail. That will show detail information on page2. As argument need to pass around 6 parameters. On the bases of those parameters detail page will generate information.
And issue is from those 6 parameters 2 can be null and cause of that below error come on view page1.
java.lang.NullPointerException
com.sun.faces.renderkit.RenderKitUtils.getCommandLinkOnClickScript(RenderKitUtils.java:934)
com.sun.faces.renderkit.html_basic.CommandLinkRenderer.getOnClickScript(CommandLinkRenderer.java:295)
com.sun.faces.renderkit.html_basic.CommandLinkRenderer.renderAsActive(CommandLinkRenderer.java:357)
com.sun.faces.renderkit.html_basic.CommandLinkRenderer.encodeBegin(CommandLinkRenderer.java:165)
javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:788)
org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils.renderChild(RendererUtils.java:433)
org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils.renderChildren(RendererUtils.java:419)
org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils.renderChild(RendererUtils.java:440)
That exception is caused by an old Mojarra 1.2 bug which indeed manifests when the <f:param> value is null. It's been fixed in Mojarra 1.2_05 (or maybe one version before or after, not sure anymore, it's been more than 6 years ago). Just upgrade to latest Mojarra 1.2 which is currently already at 1.2_15.
An alternative is to wrap it in a <c:if>, but that's plain ugly and also won't work if selectedMedicationInfoBean is been declared as the var of some parent UIData component.
<c:if test="${not empty selectedMedicationInfoBean.insurance.id}">
<f:param name="insuranceID" value="#{selectedMedicationInfoBean.insurance.id}" />
</c:if>
Another alternative is to specify a default value of 0 or -1 instead and handle accordingly in the controller.
<f:param name="insuranceID" value="#{not empty selectedMedicationInfoBean.insurance.id ? selectedMedicationInfoBean.insurance.id : -1}" />
Upgrading is the best option. You don't want to sit with a prehistoric library.

How can I reset JSF UIInput components to their managed bean values

I want to reset JSF inputs to their original managed bean values after validation failed.
I have two forms inside the same page - the first form has a commandLink to initialize the second form. The second form is rendered as a dialog whose visibility is toggled through jQuery - for the purpose of this exercise, though, I can illustrate just with two forms on the same page. Also, while I'm using PrimeFaces 2.2.x in my app, the same behaviors appear with regular h:commandLink as well.
The issue I'm having is:
click link in first form to initialize second form
submit invalid values in second form
click link in first form again to initialize second form - invalid values still there and/or UIInput state is still invalid.
For example - take the following form
<h:form id="pageForm">
<h:commandLink actionListener="#{testBean.initialize}">Initialize, no execute
<f:ajax render=":dialogForm"/>
</h:commandLink>
<br/>
<h:commandLink actionListener="#{testBean.initialize}">Initialize, execute=#this
<f:ajax execute="#this" render=":dialogForm"/>
</h:commandLink>
</h:form>
<h:form id="dialogForm">
<h:messages/>
String property - Valid: <h:outputText value="#{property.valid}"/>
<br/>
<h:inputText id="property" binding="#{property}" value="#{testBean.property}">
<f:validateLength minimum="3"/>
</h:inputText>
<br />
Int property - Valid: <h:outputText value="#{intValue.valid}"/>
<h:inputText id="intValue" binding="#{intValue}" value="#{testBean.intValue}">
<f:validateLongRange maximum="50" />
</h:inputText>
<br/>
<h:commandLink actionListener="#{testBean.submit}">
Submit
<f:ajax render="#form" execute="#form"/>
</h:commandLink>
<h:commandLink actionListener="#{testBean.initialize}">Initialize, execute=#this
<f:ajax execute="#this" render="#form"/>
</h:commandLink>
</h:form>
Bean class:
#ManagedBean
#ViewScoped
public class TestBean {
private String property = "init";
private Integer intValue = 33;
// plus getters/setters
public void submit() { ... }
public void initialize() {
intValue = 33;
property = "init";
}
}
Behavior #1
click either "Initialize" link on the pageForm
inputs get initialized to "init", "33"
now submit something invalid for both fields like "aa", "99"
now click any of the "initialize" links again (they all seem to behave the same - makes no difference whether it's in the same form or different, or whether I have specified execute="#this" or not.)
Result => UIInput.isValid() = false, both values reset though ("init", "33").
Expected => valid = true (or is this not reasonable to expect?)
Behavior #2
click either "Initialize" link on the pageForm
inputs get initialized to "init", "33"
now submit something invalid for the text field but valid for the int field ("aa", "44")
now click any of the "initialize" links again
Result => "init", valid=false; 44, valid=true
Expected => "init", valid=true; 33, valid=true
I have also looked at:
JSF 2 - Bean Validation: validation failed -> empty values are replaced with last valid values from managed bean
and
How can I populate a text field using PrimeFaces AJAX after validation errors occur?
The suggestion to explicitly reset the state of UIInputs with resetValue does work, but I'm not happy with it.
Now, I sort of understand why the isValid is not resetting - my understanding of the JSF lifecycle is that once a value is submitted to a component, isValid is not reset until the component is successfully submitted and validated and the Update Model Values phase sets the bean value. So there may be no way around explicitly resetting the valid state in this case, since I want to use #{foo.valid} for conditional CSS styling.
What I don't understand, though, is why the components that successfully validated are not re-initializing from the bean. Perhaps my understanding of the JSF lifecycle is slightly off?
I understand the rules layed out in the answer to How can I populate a text field using PrimeFaces AJAX after validation errors occur? as they pertain to an individual component but not to the form as a whole - i.e., what happens if a component succeeds validation but the validation overall fails?
In fact, there may turn out to be no better way than explicitly calling resetValue on components. In my case, all of the dialogs are in the same big JSF view tree with the underlying page that opens them. So from JSF's perspective, the same view component state including invalid input values should be preserved until we navigate away from the view, as it has no visibility into how we're toggling display attributes client-side.
The only other thing that might work is if the components that make up the dialog are actually not rendered in the JSF view tree unless they're visible. In my case, they're always rendered, using CSS to toggle visibility.

Categories