How to invoke JSF validator on keyup event? - validation

I have implemented a JSF validator based on this example.
How can I trigger it on keyup event of <h:inputText>?
I am using JSF 2.0 and Richfaces 4.1.0 Final.

You can attach ajax listeners to DOM events on any JSF HTML input component by <f:ajax> tag.
<h:inputText id="foo" value="#{bean.foo}">
<f:ajax event="keyup" execute="#this" render="fooMessage" />
<f:validator validatorId="fooValidator" />
</h:inputText>
<h:message id="fooMessage" for="foo" />
The fooValidator can be just a simple Validator implementation which you register in the faces context by #FacesValidator annotation.
#FacesValidator("fooValidator")
public class FooValidator implements Validator {
#Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
// ...
if (invalid) {
throw new ValidatorException(new FacesMessage("Fail!"));
}
}
}
See also:
Communication in JSF 2 - Ajax validation
In RichFaces it's not much different. There's only the <a4j:ajax> tag which is basically just <f:ajax> on steroids. But it does not really provide additional benefits in this particular case. See also Is there any difference between f:ajax and a4j:ajax?

Related

How to execute single input validation by #FacesValidator using ajax event and render message?

usage:JSF 2.3.2 Mojarra
while adding ajax to my jsf i met such a case:
cannnot refresh: h:message id="phoneNumber-msg" during fulfill the form
<h:messages id="validation-messages" styleClass="validation-messages"/>
<h:form>
<h:outputLabel for="phoneNumber">Phone number</h:outputLabel>
<h:inputText id="phoneNumber" value="#{bean.phoneNumber}">
<f:validator validatorId="validators.PhoneNumber"/>
<f:ajax event="blur" execute="#this" render="phoneNumber-msg"/>
</h:inputText>
<h:message id="phoneNumber-msg" for="phoneNumber"/>
[...]
<h:commandButton value="Submit" action="#{userDetails.submit}"/>
</h:form>
and validators.PhoneNumber is a #FacesValidator:
#FacesValidator("validators.PhoneNumber")
public class PhoneNumberValidator implements javax.faces.validator.Validator {
#Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException { ... }
}
ADDITIONALLY
The validation work properly(message from validators.PhoneNumber occured in both: id="validation-messages" and id="phoneNumber-msg") when refreshed by the "Submit" button that ends the form:
<h:commandButton value="Submit" action="#{userDetails.submit}"/>
</h:form>
If you think about different validation way -> at EmailAddress input I used my own class anotation (EmailAddressValidator implements ConstraintValidator) which validates by #ValidEmailAddress on the bean used in the form - it renders the email validation message properly, but here I would like to validate PhoneNumber in a different way.
Is it possible to render id="phoneNumber-msg" (that means proceeding validators.PhoneNumber during fulfill the form?

How can I highlight UIInput using Primefaces when validation upon ajax request fails?

Validator Class:
#FacesValidator("br.gov.valec.sicpd.util.CpfValidator")
public class CpfValidator implements Validator {
#Override
public void validate(FacesContext context, UIComponent component, Object value)
throws ValidatorException {
if (validateCpf(value.toString())) {
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR,"Invalid Input","Invalid Input");
((UIInput) component).setValid(false); // this line doesnt work
throw new ValidatorException(msg);
}
}
JSF snippet:
<p:inputText label="CPF" id="inputCpf"
value="#{mainBean.owner.cpf}">
<f:validator validatorId="br.gov.valec.sicpd.util.CpfValidator" />
<p:ajax event="change" update="inputNameOwner"
listener="#{mainBean.searchOwner}" />
</p:inputText>
When the form is submitted via command button primefaces highlights it automatically. How can I achieve that when ajax is fired and validation fails?
The UIInput#setValid(false) is working fine. You just forgot to tell ajax to update the input component itself. Add inputCpf or #this to <p:ajax update>.
<p:ajax ... update="#this inputNameOwner" />
That explicit UIInput#setValid(false) call in validator is by the way unnecessary. Get rid of it. JSF already does it all by itself once it catches the ValidatorException thrown by your validator.

JSF 2.0; Validator tag "disabled" depends on value from page

In my jsf application i want to validate a field which should only be validated, when one option in a SelectOneRadio is checked.
I found out, that <f:validator> has an attribute, called "disabled".
Can i use this, to check the value from another field?
I tried, but i haven't access to the value from my bean.
<h:selectOneRadio value="#{myBean.checkedSelectOneRadioValue}">
<f:selectItems value="#{myBean.valuesForSelectOneRadio}" />
</h:selectOneRadio>
<f:validator validatorId="myValidator" disabled="#{myBean.checkedSelectOneRadioValue == 'TEST'}" />
Is there any way to reach that without writing own validatorhandler?
Thanks!
The <f:validator> is a tag handler, not an UI component. All its attributes are per definition evaluated during view build time, not during view render time. The view build time is that moment when the XHTML file is been parsed into a JSF component tree as available by context.getViewRoot(). The very same view is usually reused across postbacks to the same view by returning null/void in (ajax) actions.
So you can't let a tag handler attribute depend on a render time attribute which can change during a postback request. One of the ways is to perform that check inside the custom validator itself.
E.g.
<h:inputText>
<f:validator validatorId="myValidator" />
<f:attribute name="radio" value="#{myBean.checkedSelectOneRadioValue}" />
</h:inputText>
with
#Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
if (!"TEST".equals(component.getAttributes().get("radio"))) {
return;
}
// Perform actual validation here.
}
You can alternatively also use OmniFaces <o:validator> instead. It extends the standard <f:validator> with request based evaluation of EL in attributes.
<h:inputText>
<o:validator validatorId="myValidator" disabled="#{bean.checkedSelectOneRadioValue == 'TEST'}" />
</h:inputText>
See also the showcase example and the source code from which an extract of relevance is posted below:
#Override
public void apply(FaceletContext context, UIComponent parent) throws IOException {
if (!ComponentHandler.isNew(parent)) {
return;
}
final javax.faces.validator.Validator validator = createValidator(context);
final RenderTimeAttributes attributes = collectRenderTimeAttributes(context, validator);
final ValueExpression disabled = getValueExpression(context, "disabled", Boolean.class);
((EditableValueHolder) parent).addValidator(new javax.faces.validator.Validator() {
#Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
if (disabled == null || Boolean.FALSE.equals(disabled.getValue(context.getELContext()))) {
attributes.invokeSetters(context.getELContext(), validator);
validator.validate(context, component, value);
}
}
});
}
With JSF 2.0 you can use f:ajax for a partial submit. Add this tag to your h:selectOneRadio:
<h:selectOneRadio value="#{myBean.checkedSelectOneRadioValue}">
<f:ajax render="idOfInputText"/>
<f:selectItems value="#{myBean.valuesForSelectOneRadio}" />
</h:selectOneRadio>
...
<h:inputText id="idOfInputText">
<f:validator validatorId="myValidator"
disabled="#{myBean.checkedSelectOneRadioValue eq 'TEST'}" />
</h:inputText>
Replace the renderattribute content with the real id of your input field with the validator. This assumes that the selectOneRadio and the inputText are inside the same NamingContainer.
To avoid extended discussions in comments, i will provide my suggestions as an answer to discuss it further...
At first it should be
disabled="#{myBean.checkedSelectOneRadioValue == 'TEST'}
or
disabled="#{myBean.checkedSelectOneRadioValue eq 'TEST'}
Additional, at least in ICEFaces (and MyFaces should have this function, too), you may use:
<h:selectOneRadio value="#{myBean.checkedSelectOneRadioValue}" partialSubmit="true">
<f:selectItems value="#{myBean.valuesForSelectOneRadio}" />
</h:selectOneRadio>
This should force an ajax request after changing the value of selectoneradio and the validator-disabled check should be able to get it from the bean.
If that does not work, there may be autoSubmit or similar in MyFaces...

AJAX onSubmit validation in JSF 2.0

I've started learning JSF2.0, and have come across a problem. Any advice on how to proceed would be welcome.
I have renamed form elements and classes for simplicity sake.
I have a form, for example:
<h:form id="frmSearch">
<h:inputText id="dataPoint1" value="#{bean.dataPoint1}"/>
<div id="dataPoint1Error" class="msgError">Value not found in database.</div>
<h:inputText id="dataPoint2" value="#{bean.dataPoint2}"/>
<div id="dataPoint2Error" class="msgError">Value not found in database.</div>
<h:commandButton action="#{bean.validate}" type="submit" value="Search"/>
</h:form>
The CSS class "msgError" keeps the element hidden by default.
I would like to basically have a method in the "bean" class that validates the input by checking against the database, then if the value isn't found, unhide the error message, or if it is found, then execute another method which performs the actual functionality.
In my head, it would work sort of like this in the Java (forgive any syntax errors, just typing as I think):
#ManagedBean
public class Bean {
private String dataPoint1 = "";
private String dataPoint2 = "";
public boolean validate() {
if(dao.fieldExists(this.dataPoint1) && dao.fieldExists(this.dataPoint2)) { //check the database
performFunctionality();
return true;
}
else {
return false; //and show error div on screen
}
}
public void performFunctionality() {
//do whatever
}
//getters and setters
}
Any advice would be very welcome!
Thanks!
You're not utilizing JSF builtin validation facilities. Make use of it.
Here's how it can look like:
<h:form id="frmSearch">
<h:inputText id="dataPoint1" value="#{bean.dataPoint1}" validator="#{bean.validateDataPoint}" />
<h:message for="dataPoint1" />
<h:inputText id="dataPoint2" value="#{bean.dataPoint2}" validator="#{bean.validateDataPoint}" />
<h:message for="dataPoint2" />
<h:commandButton action="#{bean.performFunctionality}" value="Search">
<f:ajax execute="#form" render="#form" />
</h:commandButton>
</h:form>
with
public void validateDataPoint(FacesContext context, UIComponent component, Object convertedValue) {
if (!dao.fieldExists((String) convertedValue)) {
throw new ValidatorException(new FacesMessage("Value not found in database."));
}
}
That performFunctionality() must be executed by the command button's action method.
When validation fails (i.e. ValidatorException is been thrown), then the message will be displayed in the <h:message> associated with the input component and the action method won't be invoked. The validator attribute can alternatively also point to a fullworthy class which implements javax.faces.validator.Validator. The <f:ajax> is been added to make it an ajax submit.
See also:
How to perform validation in JSF, how to create a custom validator in JSF
Wherever you've learnt JSF, make sure that you've also read the chapters about conversion and validation. Don't think too much the PHP/ASP/JSP/jQuery way. JSF is a full fledged component based MVC framework.

How to perform validation in JSF, how to create a custom validator in JSF

I would like to perform validation in some of my input components such as <h:inputText> using some Java bean method. Should I use <f:validator> or <f:validateBean> for this? Where can I read more about it?
The standard way is to implement the Validator interface.
#FacesValidator("fooValidator")
public class FooValidator implements Validator {
#Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
// ...
if (valueIsInvalid) {
throw new ValidatorException(new FacesMessage("Value is invalid!"));
}
}
}
The #FacesValidator will register it to JSF with validator ID myValidator so that you can reference it in validator attribute of any <h:inputXxx>/<h:selectXxx> component as follows:
<h:inputText id="foo" value="#{bean.foo}" validator="fooValidator" />
<h:message for="foo" />
Whenever the validator throws a ValidatorException, then its message will be displayed in the <h:message> associated with the input field.
You can also use EL in validator attribute of any <h:inputXxx>/<h:selectXxx> component wherein you reference a managed bean method having exactly the same method signature (the same method arguments) as Validator#validate(). I.e. taking FacesContext, UIComponent and Object arguments in this order.
<h:inputText id="foo" value="#{bean.foo}" validator="#{bean.validateFoo}" />
<h:message for="foo" />
public void validateFoo(FacesContext context, UIComponent component, Object value) throws ValidatorException {
// ...
if (valueIsInvalid) {
throw new ValidatorException(new FacesMessage("Value is invalid!"));
}
}
This is only useful if the validator needs to access another property present in the same managed bean. If it doesn't need to, then this approach is considered tight-coupling (poor practice thus), and you should split out the validator to its own class implementing the Validator interface.
You can also use <f:validator> taghandler, which would be the only way if you intend to attach multiple validators on the same component:
<h:inputText id="foo" value="#{bean.foo}">
<f:validator validatorId="fooValidator" />
</h:inputText>
<h:message for="foo" />
This will execute the #FacesValidator("fooValidator") shown above.
You can also use <f:validator binding> to reference a concrete validator instance somewhere in the EL scope, which can be specified and supplied the following way:
<h:inputText id="foo" value="#{bean.foo}">
<f:validator binding="#{fooValidator}" />
</h:inputText>
<h:message for="foo" />
#Named("fooValidator")
public class FooValidator implements Validator {
#Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
// ...
if (valueIsInvalid) {
throw new ValidatorException(new FacesMessage("Value is invalid!"));
}
}
}
Note that thus #Named is being used instead of #FacesValidator. The old #ManagedBean is also supported here instead of #Named. Historically, this was a trick in order to be able to use #EJB and #Inject in a validator. See also How to inject in #FacesValidator with #EJB, #PersistenceContext, #Inject, #Autowired
Or this way, which in turn can easily be supplied as a lambda:
<h:inputText id="foo" value="#{bean.foo}">
<f:validator binding="#{bean.fooValidator}" />
</h:inputText>
<h:message for="foo" />
public Validator getFooValidator() {
return (context, component, value) -> {
// ...
if (valueIsInvalid) {
throw new ValidatorException(new FacesMessage("Value is invalid!"));
}
};
}
Also here applies the same problem of tight-coupling when this validator doesn't need any other property from the same bean.
To get a step further, you can use JSR303 bean validation. This validates fields based on annotations. So you can have just a
#Foo
private String foo;
Without the need to explicitly register any validator in XHTML side. If you're using JPA for persistence, by default this validator will also be executed during insert/update in DB. Since it's going to be a whole story, here are just some links to get started:
Hibernate Validator - Getting started
JSF 2.0 tutorial - Finetuning validation
There's also a <f:validateBean> tag, but this is only useful if you intend to disable the JSR303 bean validation. You then put the input components (or even the whole form) inside <f:validateBean disabled="true">.
See also:
JSF doesn't support cross-field validation, is there a workaround?
How to perform JSF validation in actionListener or action method?

Resources