Rendering validation messages RichFaces - jsf

I have a form where I have a rich:select whether they choose option A or option B an h:inputText is rendered.
Initially the h:inputText corresponding to option A is rendered and if I leave it blank the requiredMessage appears and everything is OK.
Now when I select the second option of the rich:select the h:inputText for option B is rendered but if I leave it blank the requiredMessage doesn't appear.
What am I missing?
My xhtml code is as follows:
<h:panelGrid columns="3">
<h:outputLabel for="tipoPersona">Tipo de persona</h:outputLabel>
<rich:select id="tipoPersona"
required="true" value="#{userInformationController.tipoPersona}"
requiredMessage="Seleccione el tipo de persona"
defaultLabel="Seleccione una opción">
<f:selectItems value="#{userInformationController.tipoPersonaOpciones}"/>
<f:ajax event="blur" render="tipoPersonaMessage"/>
<f:ajax event="selectitem"
render="outputLabelCURP inputTextCURP messageCURP outputLabelRFC inputTextRFC messageRFC"
listener="#{userInformationController.doRenderCURP}"/>
</rich:select>
<rich:message id="tipoPersonaMessage" ajaxRendered="true"
for="tipoPersona"/>
<a4j:outputPanel id="outputLabelCURP">
<h:outputLabel for="CURP" value="CURP"
rendered="#{userInformationController.curpRendered}"/>
</a4j:outputPanel>
<a4j:outputPanel id="inputTextCURP">
<h:inputText id="CURP" required="true"
requiredMessage="Introduzca el CURP"
rendered="#{userInformationController.curpRendered}">
<f:ajax event="blur" render="curpMessage"/>
</h:inputText>
</a4j:outputPanel>
<a4j:outputPanel id="messageCURP">
<rich:message id="curpMessage" ajaxRendered="true"
for="CURP"
rendered="#{userInformationController.curpRendered}"/>
</a4j:outputPanel>
<a4j:outputPanel id="outputLabelRFC">
<h:outputLabel for="RFC" value="RFC"
rendered="#{not userInformationController.curpRendered}"/>
</a4j:outputPanel>
<a4j:outputPanel id="inputTextRFC">
<h:inputText id="RFC" required="true"
requiredMessage="Introduzca el RFC"
rendered="#{not userInformationController.curpRendered}">
<f:ajax event="blur" render="rfcMessage"/>
</h:inputText>
</a4j:outputPanel>
<a4j:outputPanel id="messageRFC">
<rich:message id="rfcMessage" ajaxRendered="true"
for="RFC"
rendered="#{not userInformationController.curpRendered}"/>
</a4j:outputPanel>
</h:panelGrid>
UPDATE
I have made some changes on the UI and now I have this
<fieldset>
<legend>Datos SURI</legend>
<h:panelGrid columns="3">
<h:outputLabel for="tipoPersona">Tipo de persona</h:outputLabel>
<rich:select id="tipoPersona"
required="true" value="#{userInformationController.tipoPersona}"
requiredMessage="Seleccione el tipo de persona"
defaultLabel="Seleccione una opción">
<f:selectItems value="#{userInformationController.tipoPersonaOpciones}"/>
<f:ajax event="blur" render="tipoPersonaMessage"/>
<f:ajax event="selectitem"
render="outputLabelCURP inputTextCURP messageCURP
outputLabelRFC inputTextRFC messageRFC
datosPersonaFisica datosPersonaMoral"
listener="#{userInformationController.doRenderTipoPersona}"/>
</rich:select>
<rich:message id="tipoPersonaMessage" ajaxRendered="true"
for="tipoPersona"/>
<a4j:outputPanel id="outputLabelCURP">
<h:outputLabel for="CURP" value="CURP"
rendered="#{userInformationController.personaFisicaRendered}"/>
</a4j:outputPanel>
<a4j:outputPanel id="inputTextCURP">
<h:inputText id="CURP" required="true"
requiredMessage="Introduzca el CURP"
value="#{userInformationController.curp}"
rendered="#{userInformationController.personaFisicaRendered}">
<f:ajax event="blur" render="curpMessage identificadorSURI"
listener="#{userInformationController.doSearchIdSURI}"/>
</h:inputText>
</a4j:outputPanel>
<a4j:outputPanel id="messageCURP">
<rich:message id="curpMessage" ajaxRendered="true" for="CURP"
rendered="#{userInformationController.personaFisicaRendered}"/>
</a4j:outputPanel>
<a4j:outputPanel id="outputLabelRFC">
<h:outputLabel for="RFC" value="RFC"
rendered="#{userInformationController.personaMoralRendered}"/>
</a4j:outputPanel>
<a4j:outputPanel id="inputTextRFC">
<h:inputText id="RFC" required="true"
requiredMessage="Introduzca el RFC"
value="#{userInformationController.rfc}"
rendered="#{userInformationController.personaMoralRendered}">
<f:ajax event="blur" render="rfcMessage identificadorSURI"
listener="#{userInformationController.doSearchIdSURI}"/>
</h:inputText>
</a4j:outputPanel>
<a4j:outputPanel id="messageRFC">
<rich:message id="rfcMessage" ajaxRendered="true" for="RFC"
rendered="#{userInformationController.personaMoralRendered}"/>
</a4j:outputPanel>
<h:outputLabel for="identificadorSURI">Identificador SURI</h:outputLabel>
<h:inputText id="identificadorSURI" disabled="true"
value="#{userInformationController.identificadorSuri}"/>
</h:panelGrid>
</fieldset>
However, I found that putting my Bean in RequestScope isn't firing the listener on both of the h:inputText (id='CURP' and id='RFC'), whereas if I put the bean in ViewScope the listener is getting fired and processed correctly.
What I need is to actually have the Bean in RequestScope because I need to create a whole new form whether the user changes the value of the rich:select. If I keep the scope in ViewScope all the data is kept within the Bean and I will then have to erase the fields when the user changes the value of the select.
Can someone explain to me why is this happening? I could'n figure out what's the trick !
Cheers

A request scoped bean is recreated on every single request, also on every single ajax request. So when you change a property by ajax to a new value other than default (e.g. the one responsible for rendered attribute), then this change won't be retained in the subsequent requests. So the rendered attribute effectively evaluates to false and the component and all its children won't be processed anymore during the submit.
The view scope is intended to solve exactly this problem. The bean will live as long as you're interacting with the same view by ajax requests, until you navigate away to a different view or recreate the view. As to the functional requirement of recreating the form on change of <rich:select>, just do that inside the doRenderTipoPersona() method.
If you really need to stick to the request scope, then you'd need to retain the bean's properties manually based on the request parameter map inside the (post)constructor.

Instead of using to event function you can use the single ajax function
<rich:select id="tipoPersona"
required="true" value="#{userInformationController.tipoPersona}"
requiredMessage="Seleccione el tipo de persona"
defaultLabel="Seleccione una opción">
<f:selectItems value="#{userInformationController.tipoPersonaOpciones}"/>
<f:ajax event="valueChange"
render="tipoPersonaMessage outputLabelCURP inputTextCURP messageCURP outputLabelRFC inputTextRFC messageRFC"
listener="#{userInformationController.doRenderCURP}"/>
</rich:select>

Well this is a solution.
<a4j:jsFunction name="onBlurRFC" execute="RFC" render = "rfcMessage identificadorSURI"
action="#{userInformationController.doSearchIdSURI}" />
<h:inputText id="RFC" required="true"
requiredMessage="Introduzca el RFC"
value="#{userInformationController.rfc}"
rendered="#{userInformationController.personaMoralRendered}" onblur="onBlurRFC()">
</h:inputText>

Related

How to pass an object to a java method using a4j:commandbutton

I have a rich:modal panel (code below). I want to pass the #{currentLeg} to the method called in action="#{legHandler.assignAndInitLoadPlanning}. But when I debug, at the method legHandler.assignAndInitLoadPlanning, resolveVariable("currentLeg"); returns an object with all its attribute values equal to null. It's attributes should not be null.
Additionally, this rich:modal is called from an a4j:commandLink onclick="showUnitDialog(); on the same jsp file. If I change this said onclick to onclick="#{legHandler.assignAndInitLoadPlanning}" the currentleg will be passed properly but i cannot do this because i need to have a popup (which is a rich:modalpanel) to display. And I am using JSF 1.
I've already tried keep alive and set variable but still not works. It seems that the currentLeg is not properly passed. Do you have any idea why?
<rich:modalPanel id="unitDialog" width="400" height="100">
<f:facet name="header">
<h:panelGroup>
<h:outputText value="Please Select Unit for the Leg"></h:outputText>
<h:outputText value="#{currentLeg.legId}"></h:outputText>
</h:panelGroup>
</f:facet>
<h:panelGrid width="100%" columns="2" columnClasses="colStyle1, colStyle2">
<h:selectOneRadio value="legHandler.unit">
<f:selectItem itemValue="kg" itemLabel="kg" />
<f:selectItem itemValue="lb" itemLabel="lb" />
</h:selectOneRadio>
</h:panelGrid>
<h:panelGrid style="text-align: center" columns="3"
columnClasses="col1, col2" width="100%">
<a4j:commandButton value="Apply" styleClass="big_btn"
id="applyButton" immediate="true"
action="#{legHandler.assignAndInitLoadPlanning}"
oncomplete="{#{rich:component('unitDialog')}.hide();}">
</a4j:commandButton>
<a4j:commandButton value="Cancel" styleClass="big_btn"
immediate="true"
id="closeUnitPopupDialog"
onclick="#{rich:component('unitDialog')}.hide();"/>
</h:panelGrid>
</rich:modalPanel>
If you're using EL 2.2+ you can simply pass the value as parameter:
<a4j:commandButton action="#{legHandler.assignAndInitLoadPlanning(currentLeg)}" … />
Otherwise use a4j:actionparam and save the value to the bean
<a4j:commandButton …>
<a4j:actionparam name="currentLeg" value="#{currentLeg}" assignTo="#{legHandler.currentLeg}" />
<a4j:commandButton>

Validator is called but error message is not displayed

when i click on the command button. validate method is getting called but the error message is not getting displayed..
here is my code..
<h:form id="form">
<h:body>
<p:panel style="width:500px">
<h:outputLabel for="year" value="Select Year: *" style="font-weight:bold" />
<p:selectOneMenu id="year" value="#{leaveBean.year}">
<f:selectItem itemLabel="Select One" itemValue="null" />
<f:selectItems value="#{leaveBean.yearDTO}" var="currentUser" itemValue="#{currentUser.name}" itemLabel="#{currentUser.name}" />
<f:validator validatorId="LeaveCardValidator" />
</p:selectOneMenu>
</p:panel>
<p:commandButton value="Submit" action="#{leaveController.leaveCard}" update="updateList,updateDetails" id="button"/>
<h:message for="year" style="color:red"/>
You seem to expect that JSF auto-updates the <h:message> on every ajax request. This is untrue. Perhaps you're confusing with PrimeFaces <p:messages> or <p:growl> which have each an autoUpdate attribute which enables you to tell them to auto-update themselves on every ajax request.
You really need to make sure that the <h:message> is covered by the ajax update. Just give it an ID
<h:message id="yearMessage" ... />
and include it in the client ID collection of the ajax update
<p:commandButton ... update="updateList updateDetails yearMessage" />
An alternative would be to replace <h:message> by <p:messages autoUpdate="true">.
Not sure where are the updateList and updateDetails are located but in the example give above you should use update="#form" instead or in addtion like this:
update="updateList updateDetails #form"
so that the form will be rendered again...
just use one of these :
update the whole form in order to update the content of
<h:message />
<p:commandButton value="Submit" action="#{leaveController.leaveCard}" update="#form" id="button"/>
or give the <h:message /> an id and id this id to the <p:commandButton/>
<h:message id="msg" for="year" style="color:red"/>
<p:commandButton value="Submit" action="#{leaveController.leaveCard}" update="updateList,updateDetails,msg" id="button"/>

primefaces dialog with inputtext as parameter

I would like to give the content of an inputText as a parameter to a function in a backing bean, I know that I could send the content in the backing bean, but it doesn't make much sense in my object model. I know that in the datatable, you can provide a function with the name of the "var", I thought I could use the same mechanism by passing the ID of the inputText, but it always sends null. Is there a way to do it ?
<p:dialog id="dialog" header="Reason for obsolescence" modal="true" widgetVar="dlg">
<h:form>
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel for="reason" value="Reason for obsolescence :" />
<p:inputText value="default" id="reason" required="true" label="reason" />
<p:commandButton id="provideReason" value="Ok" update=":form:tabView:table-metadata"
action="#{tableMetadataController.setSelectedObsolete(reason)}"
oncomplete="dlg.hide()"/>
</h:panelGrid>
</h:form>
</p:dialog>
Thanks

Losing validation with <f:ajax>

I have this form:
<h:form id="form">
<h:panelGrid columns="3" >
<h:outputLabel for="name" value="Name:" />
<h:inputText id="name" value="#{register.person.name}" >
<f:ajax event="blur" listener="#{register.validateName}" render="m_name" />
</h:inputText>
<rich:message id="m_name" for="name" ajaxRendered="false"/>
<!-- other fields -->
<h:commandButton value="Register" action="#{register.registerPerson}" >
<f:ajax execute="#form" render="out" />
</h:commandButton>
<h:outputText value="#{register.recordStatus}" id="out" />
</h:panelGrid>
If I try to register some person without a name and no error message is displayed. Instead, an error message appears when removing a person : <f:ajax execute="#form" render="out" />.
Why is this happening ?
You need to include the ID of the message in the render as well.
<f:ajax execute="#form" render="m_name out" />
You can also just render the entire form if you have more than one message.
<f:ajax execute="#form" render="#form" />
See also:
Communication in JSF 2.0 - Ajax Validation
Might be a bit late, but...
The attribute ajaxRendered of <rich:message> has a default value of true, which forces it to appear in AJAX responses.
You set it to false in Your form, and so You have to specify, which AJAX calls should re-render it.

How to submit values in a pop-up panel?

I have bean struggling to understand how to use the rich:popupPanel component in the right way. There are (at least not that I could find) few post about how to use the rich:popupPanel and how to submit values from it.
To make matter worse the panel seams to add (when checking the html) a hard coded "_content" to its component id name (to the div generated). I have tried to use aj4:region tag to partial render the complete form. But that didn't seamed to work, cause nothing where posted to managed bean. So now I have one option left, where the panel has its own form, outside the main one on the page.
I can see that the evaluation of the form (popup) values is happening, but not the execution of the bean function that persist the values (I see the POST request of the command button). The only reason I can think of at the moment, is that the pop-up panel use another bean to persist the values that the main form on the page (both of them are session scoped).
I am thinking of omit the pop-up panel all together, since it seams so hard to make this work. Maybe its a well know secret, since it so few post about it. It behaves the same if if use componentController or only a a4j:commanLink.
How is it possible to submit values from a rich:popupPanel and invoke a backing bean function to persist the pop-up form values ?
Appreciate if someone can shed some light on this, greetings Chris.
I use Richfaces 4.0-final on Glassfish 3.1
<h:form id="main_form">
<!-- Command for popup -->
<a4j:commandLink actionListener="#{userController.prepareCreateSysRequest}" oncomplete="#{rich:component('popup_sys_user_req_form:popup_sys_user_req')}.show(); return false;"
execute="#this" value="Request New Sector/Category" />
...
<a4j:commandButton action="#{projectController.Create}" ...>
</h:form>
<h:form id="popup_sys_user_req_form">
<rich:popupPanel id="popup_sys_user_req" modal="true" autosized="true" resizeable="false">
<f:facet name="header">
<h:outputText value="New Project Request" />
</f:facet>
<f:facet name="controls">
<h:outputLink value="#"
onclick="#{rich:component('popup_sys_user_req')}.hide(); return false;">
X
</h:outputLink>
</f:facet>
<h:panelGrid columns="2">
<h:outputLabel value="Request New:" />
<h:selectOneMenu id="sys_req_type" value="#{userController.selectedSysRequestType}" required="true" requiredMessage="Request Type is required" title="Request Type">
<f:selectItems value="#{userController.getSysRequestTypeItems()}">
</f:selectItems>
</h:selectOneMenu>
<h:outputLabel value="Description:" />
<h:inputTextarea id="user_req_desc" value="#{userController.selectedSysUserRequest.description}" required="true" requiredMessage="Decription is missing" />
</h:panelGrid>
<a4j:commandButton action="#{userController.CreateSysUserRequest}" onclick="#{rich:component('popup_sys_user_req')}.hide(); return false;" execute="#form" render="popup_sys_user_req_form" value="Send Request" />
</rich:popupPanel>
</h:form>
For what I have done I used to have the issue to got to submit twice only the first time.
To fix it the form got to be outside the popupPane. And also that the popupPanel should have the attibute domElementAttachment="form".
Example.
<h:form>
<rich:popupPanel id="shipmentItemUpdateDialog"
autosized="true"
domElementAttachment="form">
<f:facet name="header">
<h:panelGroup>
<h:outputText value="#{shipmentBundle.shipmentItemDetailsHeader}" />
</h:panelGroup>
</f:facet>
<f:facet name="controls">
<h:commandLink>
<h:graphicImage value="/core/images/modal/close.png"/>
<rich:componentControl target="shipmentItemUpdateDialog" operation="hide" />
</h:commandLink>
</f:facet>
<h:outputText for="shipmentItemName"
value="#{coreBundle.requiredChar} #{shipmentBundle.shipmentItemName}"
/>
<h:inputText id="shipmentItemName"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.name}"
label="#{shipmentBundle.shipmentItemName}"
size="40" >
</h:inputText>
<h:outputText for="shipmentItemCode"
value="#{coreBundle.requiredChar} #{shipmentBundle.shipmentItemCode}"
/>
<h:inputText id="shipmentItemCode"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.code}"
label="#{shipmentBundle.shipmentItemCode}"
size="40" >
</h:inputText>
<h:outputText value="#{coreBundle.requiredChar} #{shipmentBundle.shipmentItemAmount}"
/>
<h:inputText id="shipmentItemAmount"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.amount}"
label="#{shipmentBundle.shipmentItemAmount}"
size="4" >
<f:validateLongRange minimum="1"/>
</h:inputText>
<h:outputText value="#{coreBundle.requiredChar} #{shipmentBundle.shipmentItemNeedsCooling}"
/>
<h:selectBooleanCheckbox id="shipmentItemNeedsCooling"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.needsCooling}"
label="#{shipmentBundle.shipmentItemNeedsCooling}"
/>
<h:outputText for="shipmentItemDetails"
value="#{shipmentBundle.shipmentItemDetails}"
/>
<h:inputTextarea id="shipmentItemDetails"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.details}"
label="#{shipmentBundle.shipmentItemDetails}"
cols="38"
rows="5"
/>
</h:panelGrid>
<h:panelGrid columns="1" dir="LTR">
<h:panelGrid columns="2" dir="LTR">
<a4j:commandButton value="#{coreBundle.acceptButton}"
action="#{shipmentItemController.onUpdate()}"
render="shipmentItemsTable">
</a4j:commandButton>
<h:commandLink value="#{coreBundle.closeLink}"
immediate="true">
<rich:componentControl target="shipmentItemUpdateDialog" operation="hide" />
</h:commandLink>
</h:panelGrid>
<h:outputText value="#{coreBundle.requiredText}"/>
</h:panelGrid>
</rich:popupPanel>
</h:form>
I hope this helps.
I think you got it right.. think of the pop-up as a regular page. To submit and close the pop-up, do something like this:
<a4j:commandButton value="Save" onclick="#{rich:component('panelId}.hide();" render="..."/>
Hope this helps..

Resources