Ajax validation, different Messages - ajax

Hi guys I have a real problem with my validation in JSF. I want to validate a Mail-Address if it's already used and the correct mail format. Here are the picture how it should look.
https://www.dropbox.com/s/bs9nshmuurauc2e/Unbenannt.JPG
I hope can understand the problem. I don't now how I can implement it.
Can I set different messages for different events?
I use primefaces 3.5 and jsf 2.1
<p:row>
<p:column style="width:400px">
<h:outputLabel for="email" styleClass="outputRight" value="#{msg['regi_mail']}" />
</p:column>
<p:column style="width:350px">
<p:inputText style="width:350px" requiredMessage="#{msg['regi_mail_valid']}" validatorMessage="#{msg['regi_mail_valid']}" id="email" value="#{regiBean.user.EMAIL}" required="true">
<f:validateRegex pattern="^[_A-Za-z0-9-\+]+(\.[_A-Za-z0-9-]+)*#[A-Za-z0-9-]+(\.[A-Za-z0-9]+)*(\.[A-Za-z]{2,})$" />
<f:ajax event="blur" render="format user" />
</p:inputText>
</p:column>
<p:column style="width:410px">
<h:panelGroup id="mail" class="fa fa-question-circle fa-2x" />
<p:overlayPanel for="mail" showEvent="mouseover" hideEvent="mouseout" hideEffect="fade">
<p:panel>
TEXTTEXTTEXT
</p:panel>
</p:overlayPanel>
<p:message id="format" for="email" />
</p:column>
</p:row>
<p:row>
<p:column style="width:400px">
<h:outputLabel styleClass="outputRight" value="Username" />
</p:column>
<p:column style="width:350px">
<h:outputLabel id="user" style="color: green;" value="#{regiBean.user.EMAIL}" />
</p:column>
<p:column>
<h:panelGroup id="us" class="fa fa-minus-square fa-2x" />
<h:panelGroup/>
</p:column>
</p:row>

I've done something like this but front end only different.
XHTML File
The Bean Code
I hope you will get some help from this.

This may be a little late, I see the question was asked in Feb already. However, seems this would be a case where you should rather supply a custom validator. Here is my suggestion:
Remove the validatorMessage attribute from you id="email" element. Also remove the f:validateRegex validator in that input element.
Create a custom validator. It should:
Have a #ManagedBean (or similar) annotation (so that the EL in your JSF page can reference it)
implement javax.faces.validator.Validator
override the validate() method. In it you do your validations, e.g. check your regexp as well as query the database for existing addresses via e.g. JPA (or an EJB business method). If validation fails, you throw a javax.faces.validator.ValidatorException, that is constructed with a javax.faces.application.FacesMessage instance containing the relevant error message (there are various constructors, find an applicable one).
If you do not want to code something in this validator, but "pass it in" from the JSF page, you could do that via attribute passing. Useful if you e.g. would want to pass in your (i18z'ed) error message, values of other fields on the form, etc. etc. The only things available inside the validate() method by default is the FacesContext, the UIComponent, and the value that is validated. (See example below.)
Modify your JSF similar to the example below.
Example - Validator class:
#ManagedBean public class MyEmailValidator implements Validator {
#EJB UserEJBLocal userEJB; // supposing you want to use a method in there to get list of e-mail addresses
private static final String REGEXP = "^[_A-Za-z0-9-\+]+(\.[_A-Za-z0-9-]+)*#[A-Za-z0-9-]+(\.[A-Za-z0-9]+)*(\.[A-Za-z]{2,})$";
#Override public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
if (! Pattern.matches(REGEXP, value.toString())) {
throw new ValidatorException(new FacesMessage(component.getAttributes().get("formatMsg")));
}
List existingAddresses = userEJB.getAllAddresses(); // or whatever method your are using to obtain current addresses, e.g. JPA.
if (existingAddresses.contains(value.toString()) {
throw new ValidatorException(new FacesMessage(
FacesMessage.SEVERITY_ERROR,
"The address already exists." // could also be passed in as attribute, etc.
));
}
}
}
Example - JSF snippet:
<p:inputText id="email" value="#{regiBean.user.EMAIL}"
requiredMessage="#{msg['regi_mail_valid']}" required="true"
>
<f:validator binding="${myEmailValidator}" />
<f:attribute name="formatMsg" value="#{msg['regi_mail_valid']}" />
: <!-- other attributes, if needed -->
<f:ajax event="blur" render="email-msg user" />
</p:inputText>
:
<p:message id="email-msg" for="email" />
Well, the above example may not be complete, but might point you in the right direction.
OK, so maybe you want to check the current row's e-mail against the e-mails in the other rows? You are a bit out of luck... The only way I can think of is to somehow gather them all into a list, which you can pass via another attribute to the validator. Not very easy with a dynamic table... You might want to rethink your process.

Related

How to pass a parameter in p:ajax when we used it with p:inputText?

I need to pass a parameter in my p:ajax method . there is a <p:inputText> and when I finish typing my input Box have to update my p:ajax method. But i am not able to send the parameter in my method.
My jsf page is :
<h:outputText value="#{msg['elicense.contractorFormRenewal.personal.registrationNo']}"/>
<p:inputText id="registrationNo" value="#{renewalContractorBean.registrationNo}" required="false" label="Registration No">
<p:ajaxlistener="#{renewalContractorBean.readLicenseDetailsById(renewalContractorBean.registrationNo)}/>
</p:inputText>
and my method in bean is
public void readLicenseDetailsById(String id) {
FirmOrCompany firmOrCompany = contractorRenewableService.readLicenseDetailsById(id);
this.setLicenseName(firmOrCompany.getLicensePersonName());
this.setClassofLicense(firmOrCompany.getLicenseAppliedFor());
}
There is no <p:ajaxListener>, i don't know if you missed your code or the question.
Considering you made a mistake in the question, your method should work fine, you just forgot to set the event=blur in <p:ajax>, so it get called once you leave the inputTextBox(means that the user already done typing)
<p:inputText id="registrationNo" value="#{renewalContractorBean.registrationNo}" required="false" label="Registration No">
<p:ajax event="blur" listener="#{renewalContractorBean.readLicenseDetailsById()}/>
</p:inputText>
Check that if you want to update another component, based on the changes you made in your bean, you must specify the id of that component in <p:ajax>, <p:ajax event="blur" update"IdOfTheComponent" ....>
Also, you don't have to pass properties which is already in your bean as a parameter, you can just get it in your bean.
Finally, in renewalContractorBean:
public void readLicenseDetailsById()
{
String id = this.registrationNo;
FirmOrCompany firmOrCompany= contractorRenewableService.readLicenseDetailsById(id);
this.setLicenseName(firmOrCompany.getLicensePersonName());
this.setClassofLicense(firmOrCompany.getLicenseAppliedFor());
}
Hi did you tryupdate="tableid" ? When I delete from a list which in p:dataTable, JSF can update this dataTable I hope this will be helpful.
Here is my code to update my p:datatable
<p:dataTable id="tbl" value="#{borrowerBean.borrowers}" var="bor">
<p:column>
<f:facet name="header">
<h:outputLabel>ID: </h:outputLabel>
</f:facet>
<h:outputLabel value="#{bor.id}"/>
</p:column>
.
.
.
<p:commandButton value="Delete" action="#{user.deleteBorrower(bor.id)}" update="tbl"/>
</p:column>
</p:dataTable>

Passing <p:inputText> values to Bean using ajax

I am having the h:inputText which having a text and by ajax request how can i send it's values to bean class and the values will be validated in further action begin at bean class ..
view page code is
<h:form>
<p:panel id="panel" header="Login Panel" style="margin:0 auto;width:350px;margin-top:15%;">
<p:panelGrid columns="3" id="pgrid1" styleClass="theme" >
<p:outputLabel value="User Name:" />
<p:inputText id="name" value="#{loginBean.name}" required="true" requiredMessage="Name is required">
<f:ajax event="blur" render="label" listener="loginBean.validateName" ></f:ajax>
<!--Here the ajax event working properly but how can i get the inputText value when ajax event is invoked-->
</p:inputText>
<p:message for="name" style="color: red;" />
</p:panelGrid>
<p:commandButton type="Submit" value="Submit" action="#{loginBean.validate}" update="pgrid1" />
</p:panel>
My Bean class Code is :
public void validateName(AjaxBehaviorEvent e)
{
//Here i need inputText value..how can i handle this task..!!
}
JSF has already set the #{loginBean.name} value at that moment. Just access it directly.
public void validateName(AjaxBehaviorEvent e)
{
System.out.println(name); // Look, JSF has already set it.
// ...
}
You've by the way an EL syntax error in <f:ajax listener> which causes the listener method never to be invoked, but I'll bet it to be just carelessness during preparing the question as you mentioned that it is "working properly". In the future questions, please edit code in the real development environment and copypaste real working code instead of blindly editing the code in the question editor.

Dynamic disable validator when click checkbox

I got one number validator and one checkbox in my jsf. When a checkbox is selected then the number validator will check validation. When checkbox is unselected, the validation will skip it.
Please see my code
<h:outputText value="#{trancheResources.label_enable}:" />
<p:selectBooleanCheckbox id="enableCheckBox" itemLabel="#{trancheResources.label_yes}" value="#{trancheBean.enableCheck}" disabled="#{trancheBean.readonly}">
</p:selectBooleanCheckbox>
<p:outputLabel for="acceptableMinVal" value="#{trancheResources.label_acceptableMinVal}:" />
<pe:inputNumber id="acceptableMinVal" value="#{trancheBean.trancheValidation.podMin}" disabled="#{trancheBean.readonly}" maxValue="999"
required="#{trancheBean.requiredIfEnableCheck}" requiredMessage="#{trancheResources.label_acceptableMinVal} is required.">
<f:validateDoubleRange disabled="#{trancheBean.cValidation}" minimum="1.00" />
</pe:inputNumber>
<p:outputLabel for="acceptableMaxVal" value="#{trancheResources.label_acceptableMaxVal}:" />
<pe:inputNumber id="acceptableMaxVal" value="#{trancheBean.trancheValidation.podMax}" disabled="#{trancheBean.readonly}" maxValue="999"
required="#{trancheBean.requiredIfEnableCheck}" requiredMessage="#{trancheResources.label_acceptableMaxVal} is required.">
<p:ajax event="keyup" listener="#{trancheBean.acceptableMaxValOnkeyup}" ></p:ajax>
</pe:inputNumber>
<p:outputLabel for="exceptionMinVal" value="#{trancheResources.label_exceptionMinVal}:" />
<pe:inputNumber id="exceptionMinVal" value="#{trancheBean.trancheValidation.podExceptionMin}" disabled="#{trancheBean.readonly}" maxValue="999"/>
<p:outputLabel for="exceptionMaxVal" value="#{trancheResources.label_exceptionMaxVal}:" />
<pe:inputNumber id="exceptionMaxVal" value="#{trancheBean.trancheValidation.podExceptionMax}" disabled="#{trancheBean.readonly}" maxValue="999"/>
Please guide me to a solution. I have no idea on how to solve this.
I'll provide you with this sample answer and you can use it to apply it to yours. This approach is based on Pankaj Kathiriya's comment since that seems to be what you want to do.
In the sample code below, you have two <h:inputText> (substitute this component with yours <pe:inputNumber>). Their rendered attribute value will change every time you check/uncheck the <p:selectBooleanCheckBox>. When rendered evaluates to true, the <h:inputText> with validation will appear, the one without validation disappears (and vice versa).
The <selectBooleanCheckBox> will fire a ValueChangeEvent every time you check/uncheck it. You also need to make sure to set immediate to true so that it can be processed first (one phase before). Then call renderResponse in your listener to skip the remaining life cycles. Validation will kick in for the <h:inputText> with validation if you don't and you will see a validation error message when the switch occurs. Finally, for the <h:selectBooleanCheckBox>, you want to submit the form when the selection/deselection occurs. This can be done with javascript by setting its onchange attribute to submit() (e.g. onchange = "submit()"). Try to run the code so this could all make sense.
Again, keep in mind this is just a sample to help guide you to your solution.
public class SampleBean {
private boolean renderValidatedForm;
private String firstInput;
private String secondInput;
//Constructor ommitted
//Setters and getters ommitted
public void toggleRender(ValueChangeEvent e) {
boolean valueCheck = (Boolean) e.getNewValue();
renderValidatedForm = valueCheck;
FacesContext.getCurrentInstance().renderResponse();
}
}
The xhtml
<h:form>
<h:panelGrid>
<h:panelGroup>
<h:outputLabel for="enableCheckBox" value="Check to view form with validation"/>
<p:selectBooleanCheckbox id="enableCheckBox" value="#{sampleBean.renderValidatedForm}"
onchange="submit()"
valueChangeListener="#{sampleBean.toggleRender}"
immediate="true"/>
</h:panelGroup>
<h:panelGroup>
<h:outputLabel for="withValidation" value="Form with validation"
rendered="#{sampleBean.renderValidatedForm}"/>
<h:inputText id="withValidation" value="#{sampleBean.firstInput}"
required="true" rendered="#{sampleBean.renderValidatedForm}"/>
<h:message for="withValidation"/>
</h:panelGroup>
<h:panelGroup>
<h:outputLabel for="noValidation" value="Form without validation"
rendered="#{!sampleBean.renderValidatedForm}"/>
<h:inputText id="noValidation" value="#{sampleBean.secondInput}"
rendered="#{!sampleBean.renderValidatedForm}"/>
</h:panelGroup>
</h:panelGrid>
<h:commandButton value="Submit"/>
</h:form>

JSF 2 ProcessValidationPhase Fails Due to Uninitialized Managed Bean Property

I am looking for best-practice guidance on how to implement the following. I am using JSF2, Spring 3, PrimeFaces 3.3, MyBatis.
REQUIREMENT:
I have a data entry screen with input fields linked to VO object which is a property on the managed bean. The user can either create a new record, or search for existing records to edit.
When the edit an existing record option is selected, a dialog box appears where the user is able to search and retrieve a list of potential records to select from.
They are only able to select one record to edit at a time. Once they have made their selection, the dialog box closes, and the VO object is populated with the selected data ready for the user to edit.
PROBLEM:
When the search form is submitted to retrieve a list of potential records for editing, the VO object has not yet been initialised and causes the ProcessValidationPhase to fail the process with a "Target Unreachable".
What is the best way to implement this scenario? Should the VO object be initialised with blank values in the managed bean? Or should there be an initialise method on the VO object that is called during the initialisation of the managed bean?
DataEntry.XHTML
The main data entry fields:
<p:panelGrid id="dataEntry">
<p:row>
<p:column style="width:200px;">
<h:outputLabel value="Field 1:"/></p:column>
<p:column>
<p:inputText value="#{managedBean.dataEntryVo.field1}"
style="width:50px;"
disabled="true"/>
</p:column>
</p:row>
<p:row>
<p:column>
<h:outputLabel value="Field 2:"/>
</p:column>
<p:column>
<p:inputText value="#{managedBean.dataEntryVo.field2}"
style="width:50px;"
disabled="true"/>
</p:column>
</p:row>
</p:panelGrid>
The command button on the dialog box used to retrieve a list of possible records for selection to edit:
<p:commandButton id="retrieveDataCb"
value="Retrieve"
actionListener="#{managedBean.retrieveDataEntryList}"
update=":dataEntryForm:retrievedList">
</p:commandButton>
Many thanks
Initialising the search criterion to a dummy object will definitely work. Not very neat but it works. On the other hand, you could try using a data container component like a <p:dataGrid/> or <p:dataTable/>. There is a var attribute that will let you get away with null references like the case that you are trying to achieve. The var attribute compensates for empty datasets. That being said, you can now have a List<DataEntryVo> in your backing bean and then in your view:
<p:dataGrid id="dataEntry" value="#{managedBean.theVoList}" var="vo">
<p:panel>
<p:panelGrid>
<p:column style="width:200px;">
<h:outputLabel value="Field 1:"/>
</p:column>
<p:column>
<p:inputText value="#{vo.field1}" style="width:50px;" disabled"true"/>
</p:column>
<p:row>
<p:column>
<h:outputLabel value="Field 2:"/>
</p:column>
<p:column>
<p:inputText value="#{vo.field2}" style="width:50px;" disabled="true"/>
</p:column>
</p:row>
</p:panelGrid>
</p:panel>
</p:dataGrid>
Another alternative, you could avoid binding the input fields to an object in your managed bean altogether, instead binding the input fields to the managed bean directly as in <p:inputText binding="#{vo.field1Input}" style="width:50px;" disabled="true"/> and in your backing bean you will have UIcomponent field1Input = new HtmlInputText(); (or whatever the class is for primefaces and then call field1Input.getValue() or field1Input.setValue() according to your needs. It's also a good idea to make your bean a ViewScoped bean to avoid unnecessary trouble getting this solution to work.

JSF : How to refresh required field in ajax request

Ok, here you are the core problem.
The page. I have two required "input text".
A command button that changes the bean value and reRenderes the "job" object.
<a4j:form id="pervForm">
SURNAME:<h:inputText id="surname" label="Surname" value="#{prevManager.surname}" required="true" />
<br/>
JOB:<h:inputText value="#{prevManager.job}" id="job" maxlength="10" size="10" label="#{msg.common_label_job}" required="true" />
<br/>
<a4j:commandButton value="Set job to Programmer" ajaxSingle="true" reRender="job">
<a4j:actionparam name="jVal" value="Programmer" assignTo="#{prevManager.job}"/>
</a4j:commandButton>
<h:commandButton id="save" value="save" action="save" class="HATSBUTTON"/>
</a4j:form>
Here the simple manager:
public class PrevManager
{
private String surname;
private String job;
public String getSurname()
{
return surname;
}
public void setSurname(String surname)
{
this.surname = surname;
}
public String getJob()
{
return job;
}
public void setJob(String job)
{
this.job = job;
}
public String save()
{
//do something
}
}
Let's do this:
Write something on the Job input text (such as "teacher").
Leave empty the surname.
Save.
Validation error appears (surname is mandatory).
Press "Set job to Programmer": nothing happens.
Checking the bean value, I discovered that it is correctly updated, indeed the component on the page is not updated!
Well, according to the JBoss Docs I found:
Ajax region is a key ajax component.
It limits the part of the component
tree to be processed on the server
side when ajax request comes.
Processing means invocation during
Decode, Validation and Model Update
phase. Most common reasons to use a
region are:
-avoiding the aborting of the JSF lifecycle processing during the
validation of other form input
unnecessary for given ajax request;
-defining the different strategies when events will be delivered
(immediate="true/false")
-showing an individual indicator of an ajax status
-increasing the performance of the rendering processing
(selfRendered="true/false",
renderRegionOnly="true/false")
The following two examples show the
situation when a validation error does
not allow to process an ajax input.
Type the name. The outputText
component should reappear after you.
However, in the first case, this
activity will be aborted because of
the other field with required="true".
You will see only the error message
while the "Job" field is empty.
Here you are the example:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<style>
.outergridvalidationcolumn {
padding: 0px 30px 10px 0px;
}
</style>
<a4j:outputPanel ajaxRendered="true">
<h:messages style="color:red" />
</a4j:outputPanel>
<h:panelGrid columns="2" columnClasses="outergridvalidationcolumn">
<h:form id="form1">
<h:panelGrid columns="2">
<h:outputText value="Name" />
<h:inputText value="#{userBean.name}">
<a4j:support event="onkeyup" reRender="outname" />
</h:inputText>
<h:outputText value="Job" />
<h:inputText required="true" id="job2" value="#{userBean.job}" />
</h:panelGrid>
</h:form>
<h:form id="form2">
<h:panelGrid columns="2">
<h:outputText value="Name" />
<a4j:region>
<h:inputText value="#{userBean.name}">
<a4j:support event="onkeyup" reRender="outname" />
</h:inputText>
</a4j:region>
<h:outputText value="Job" />
<h:inputText required="true" id="job1" value="#{userBean.job}" />
</h:panelGrid>
</h:form>
</h:panelGrid>
<h:outputText id="outname" style="font-weight:bold" value="Typed Name: #{userBean.name}" />
<br />
</ui:composition>
Form1: the behaviour is incorrect. I need to fill the job and then the name.
Form2: the behaviour is correct. I do not need to fill the job to see the correct value.
Unfortunately using Ajax region does not help (indeed I used it in a bad way ...) because my fields are both REQUIRED. That's the main different.
Any idea?
Many thanks.
This problem is also identified in JSF 2 and explained in detail in this related answer: How can I populate a text field using PrimeFaces AJAX after validation errors occur?
Summarized, the answer is that you need to clear the state of the EditableValueHolder component when it's about to be ajax-rendered, but which isn't included in the ajax-execute, by calling the methods setValue(null), setSubmittedValue(null), setLocalValueSet(false), setValid(true). Note: in JSF 2 you would have used the convenience method resetValue() instead.
Given that your "job" input field has the client ID prevForm:job, here's how you could clear it inside the action listener method associated with the "Set job to programmer" button:
UIInput input = (UIInput) context.getViewRoot().findComponent("prevForm:job");
input.setValue(null);
input.setSubmittedValue(null);
input.setLocalValueSet(false);
input.setValid(true);
Using a4j:actionparam will set the value, but will not help you bypass validation in this case. Validation happens on the component (not the bean property). So, when you submit, the component value is still empty. Hope this helps.
When you click "Set job to Programmer" nothing happens because you are not reRendering your message component. If you do, you'll be able to see the validation message.
You need to reRender the message because its a <a4j:commandButton/>, not a simple <h:commandButton/>
Try to use the prop. immediate in "Set job to Programmer" button and check if it will update the field.
<a4j:commandButton value="Set job to Programmer" ajaxSingle="true" reRender="job" immediate="true">
<a4j:actionparam name="jVal" value="Programmer" assignTo="#{prevManager.job}"/>
</a4j:commandButton>
*I dont think "ajaxSingle" necessary here..
Maybe you can get a new problem.. using immediate, the bean value will be not updated (MAYBE!). If it happens, make a bean method which sets manually the bean value.
Otherwise, if the bean value was updated and the field still empty, try to put the "job" field into a <a4j:outputPanel/> and reRender the outputPanel.
<a4j:outputPanel id="myPanel">
<h:inputText value="#{prevManager.job}" id="job" maxlength="10" size="10" label="#{msg.common_label_job}" required="true" />
</a4j:outputPanel/>
<a4j:commandButton value="Set job to Programmer" reRender="myPanel" immediate="true">
<a4j:actionparam name="jVal" value="Programmer" assignTo="#{prevManager.job}"/>
</a4j:commandButton>
More info about <a4j:outputPanel/> here.

Resources