I am using JSF validation to simply check that the length of a field is 15, if not an error message is shown. My issue with this approach is
that user enters a number which is the correct length and clicks a button and some information is displayed about it. The second time when the user enters a number whose length is <15 then the validation error is shown BUT the information about the previous number remains on the screen.
My trouble is I am not sure how to do a refresh of the page. I do the validation like this:
<h:inputText id="imei" value="#{imeiValidationHandler.imei}" required="true">
<f:validateLength minimum="15" maximum="15"/>
</h:inputText>
Any ideas much appreciated.
On your information section have a attribute that suppresses the display if the length of the imei is less than ideal. eg:
<h:outputText value="#{imeiInformation.value}" rendered="#{sometest}" />
You may also want to look into a4j and rich faces for using AJAX to render your page as things change on the client.
Related
First post here, so bare a bit with me. Searched a lot, but either because I was to blind or because I just didn't use the correct search strings, I haven't found any answer relevant to my problem.
Basically, I have a web application written in Java and using Primefaces. I'm using a p:layout, having the main content in the center unit, the header in the north and the footer in the south unit of the layout. The west layout unit holds a p:poll which runs every two seconds cand calls a js function when the oncomplete event is triggered.
So far so good. The thing is that on a certain page, in the center layout unit, I have a f:viewParam which accepts only longs and, even though the value is valid, when the above poll gets executed, the requiredMessage from the f:viewParam appears.
After doing some intensive search, I've found that by adding a ignoreAutoUpdate="true" to the p:poll, the messages from the f:viewParam will not get triggered and the warning telling that I have to provide a valid id isn't shown.
So, my question is: by having the ignoreAutoUpdate="true" in my p:poll will compromise, by any chance, the f:viewParam validation? Or is it safe to leave it there?
Here is the relevan parts from my layout:
The poll form the west layout unit:
<h:form id="liveQueueForm">
<p:remoteCommand name="rcStart" action="#{liveQueueMB.startPoll()}"/>
<p:remoteCommand name="rcStop" action="#{liveQueueMB.stopPoll()}"/>
<p:poll id="liveQueueUpdater" delay="10" widgetVar="livePoll" interval="2" listener="#{liveQueueMB.init}" oncomplete="updateLiveQueue(xhr, status, args);" autoStart="true" partialSubmit="true" ignoreAutoUpdate="true" immediate="true" />
<div id="live-queue">
<div id="queue-holder"></div>
</div>
</h:form>
The f:metadata block which holds my f:viewParam:
<f:metadata>
<f:viewParam name="callId" value="#{viewInboundCallDetailsMB.callId}" required="true" requiredMessage="Please provide a valid call ID" converter="javax.faces.Long" converterMessage="The call ID is not numeric" />
<f:viewAction action="#{viewInboundCallDetailsMB.init}"/>
</f:metadata>
Thank you!
From Primefaces manual about ignoreAutoUpdate:
"If true, components which autoUpdate="true" will not be
updated for this request. If not specified, or the value is
false, no such indication is made."
Which means that it's not going to do update your viewParam component, and other components that have autoUpdate="true".
It's not going to disable the validation on it. (Unless of course, if you are using your poll for validation, which i presume you are not)
I'm using PrimeFaces 5.0 and have a problem with the basic validation messages.
I've many <p:inputText> fields that are all required, how can I link a single <p:messages> to all fields?
If I use the for attribute I can link it just to a single text field.
If I don't use the for attribute the <p:messages> tag catches also messages that are not for him (it duplicates the messages sent to the <p:growl> tag for example).
Just tell the <p:messages> to not redisplay (duplicate, as you say) the already displayed messages. Provided that the <p:growl> in question is being placed in the view before the <p:messages>, then it's a matter of setting its redisplay attribute to false.
<p:growl ... />
...
<p:messages ... redisplay="false" />
I have a complex page with a p:commanButton with actionListener and immediate="true"
Upon clicking this commandButton, I need to process a single inputField(thus skipping rest of the form). The problem is, that the inputField has a validator which I'd like to use only in full page submit.
<p:inputText id="#{cc.attr.id2}_input" value="#{myBB.value}"
immediate="true">
<f:validateLength minimum="4"/>
</p:inputText>
<p:commandButton id="#{cc.attr.id2}_search" immediate="true"
process="#{cc.attr.id2}_input #this"
actionListener="#{myBB.listener}">
</p:commandButton>
When I do this with i.e. 3 letters in the inputText, the myBB.value is not updated because of the failed validation. So I'd like to disable the validator for the inputField for the immediate processing by the commandButton. But I don't know how.
I know I can get the value from the ExternalContext, but this seems like a very hacky solution to me(and in my case is not even applicable, because it's inside composite component and I have no way of knowing the clientId of the textField.)
I also know about disabled attribute of the validator tag, but I have no idea how could I put that to use in this situation.
EDIT: I've changed a code a bit, because the IDs I'm using are actually not as simple as I first stated and don't allow me to use simple proposed solution.
I use Mojarra 2.2.4 and Primefaces 4.0
So, first of all, you haven't got the problem with immediate, but rather with <f:validateLength> validator.
That is, to rephrase your question, you'd like to skip validation of a given component in case the particular button is clicked.
Depending on whether you are on Mojarra 2.1.18+ or not there are two solutions. The first one is quite straightforward: use the disabled attribute of <f:validateLength>, while the other one takes into account issue 1492. As we've nowadays have advanced past the aforementioned version of Mojarra, I'll post the first and easier solution, otherwise, scroll through the excellent answers to Why does f:validateDoubleRange only work for #SessionScoped? and Disabled attribute of <f:validateLength> does not evaluate request parameters by BalusC.
So, the solution is the following:
<h:form id="formId">
<p:inputText id="inputId" value="#{myBB.value}">
<f:validateLength minimum="4" disabled=#{not empty param['formId:buttonId']}" />
</p:inputText>
<p:commandButton id="button" process="#this inputId" actionListener="#{myBB.listener}" />
</h:form>
As a side note, you can see that I didn't use immediate attribute at all because I supposed that you abused it to perform a given task. With the rise of AJAX in particular within JSF-based applications you can now easily group a subset of input elements validation by specifying the process attribute of <p:commandButton> or <p:ajax> instead of the previously used prioritized validation especially in synchronous requests. Only those components whose ids are supplied will be processed on the server and all other components will be omitted prom processing lifecycle. Also note that process="#this ..." is also mandatory to execute actions associated with the button itseld.
Regarding the appropriate usage of immediate I'd strongly suggest to refer to the classics: Debug JSF lifecycle blog post by BalusC to check whether you've used it correctly.
I have a form that has a field that needs to be rendered as a read-only value when in edit mode and as a drop-down select list when in create mode.
The read-only field (used in edit mode) is rendered as plain text using <h:outputText>. In create mode, the field is rendered <h:selectOneListbox> that has a required attribute of "true".
It seems to work as I expect most of the time, but occasionally I get a validation error when in edit mode (the select list box is not rendered) .
Here is the code snippet that has both fields defined with their rendered attributes set using the same boolean value (just one field negates the boolean to toggle).
<h:outputLabel id="lblBusinessArea" value="Business Area:" />
<h:panelGroup id="baGroup">
<h:selectOneListbox id="businessAreaList" size="1"
rendered="#{shiftDetailsController.canEditBusinessArea}"
converter="businessAreaConverter"
value="#{shiftDetailsController.selectedBusinessArea}"
label="Business Area"
required="true">
<f:selectItems id="businessAreaListItems" value="#{shiftDetailsController.businessAreas}" />
<a4j:support id="businessAreaA4j" event="onchange"
ajaxSingle="true" reRender="deploymentGroupList, positionPayGroupList, sapPremCodeList" />
</h:selectOneListbox>
<h:outputText id="businessAreaRO"
rendered="#{!shiftDetailsController.canEditBusinessArea}"
value="#{shiftDetailsController.selectedBusinessArea.busAreaDesc}" />
</h:panelGroup>
Below is a screen clipping showing the field (in edit mode) rendered as read only. The "save" button was clicked and I get a validation error message that the field is required.
The value should be there in the backing bean because the value displayed is from the same object (shiftDetailsController.selectedBusinessArea). The output text uses the description field on the business area ojbect and the select field uses the whole object where the SelectItem has the description in the label.
Any idea how this could be occurring? I could set the required attribute using the same boolean value that determines the rendered state...so that it is only required when it is rendered...but since this problem is intermittent...I don't know that will really help.
I also verified that no other components on the page inadvertently have a label value of "Business Area" (which is being used in the validation message) to mislead me in which component truly has a null value; this is the only one that has the label of "Business Area".
I figured out what was happening with this issue.
Prior to submitting the form and receiving the validation error. I was making a change that caused the flag controlling the two components' visibility to be reversed.
rendered="#{shiftDetailsController.canEditBusinessArea}"
In other words, what I was doing on the form was causing the canEditBusinessArea to change values. But, I was not re-rendering the panel group ("baGroup") to cause the UI to reflect the update.
Thus, when my form was submitted the component during the validation phase was seen as being required...triggering the validation to happen. As soon as I added "baGroup" to the reRender of the action that was flipping the edit business area flag, the UI began reflecting the update and the submitted form had the value.
I'm experiencing some problems when using the "rendered" attribute with ajax behavior. I'll paste the code so I think it will be a lot more clear:
<h:selectOneMenu value="#{registrarVentaController.esCobroChequeString}">
<f:selectItem itemLabel="Efectivo" itemValue="false"/>
<f:selectItem itemLabel="Cheque" itemValue="true"/>
<f:ajax execute="#this" render="#form"/>
</h:selectOneMenu>
<h:panelGroup id="panelMonto">
<span>Monto:</span>
<h:inputText value="#{registrarVentaController.monto}" rendered="#{registrarVentaController.banCobroCheque}"/>
<h:inputText value="#{registrarVentaController.monto}" rendered="#{not registrarVentaController.banCobroCheque}"/>
</h:panelGroup>
My "#{registrarVentaController}" is just a View Scoped JSF Managed Bean with appropiate setters/getters.
This way it works, I mean, when user selects option "Efectivo", panelGroup "panelMonto" will get updated and we'll see the first inputText, and conversely when user selects option "Cheque" user will see the second inputText.
For this approach I used "f:ajax" component where I updated the whole #form to get this behavior work and I just want to update panelGroup "panelMonto" (using render="panelMonto" It doesn't work at all (I even try with full scope resolution :formName:panelMonto with no result).
I just want to have rendered work with ajax="idComponent" or similar behavior to show certain parts according what user have selected.
Best Regards!
Note (One solution)
I managed to get a solution (taking as an input
JSF rendered is not working
and a bit of myself). I've just moved to a new form the part that I'm
interested in filtering according what user selected. This way I still
use #form ajax's render and it will just render this new form (not the
whole form as I was using!) Neverthless I'm still wondering if there
is a solution to not used #form and just the component/s ID.
what if you check with
render=":panelMonto"
not
render=":formName:panelMonto"
still not working?
this should work only with
render="panelMonto" //because is in the same form
Can you add more code?
Also can you check with your browser (in chrome: right click, inspect element, network) to see if there is any activity?? perhaps is rendering the same thing because of you...