As you probably know, PrimeFaces support Bean Validation. Actually,
PrimeFaces comes with a client side
validation framework integrated with Bean Validation Specification. Basically, PrimeFaces obtains via a set of
classes (located in org.primefaces.validate.bean)
the server side validation constraints for each type of supported validators.
These constrains will be used in a JavaScript file named beanvalidation.js to
perform the validation on client side and generate the corresponding messages.
For example, let's suppose that we have the following bean:
@Named
@RequestScoped
public class
DataBean {
@Size(min = 2, max = 25)
private String name;
@Size(min = 2, max = 10)
private String surname;
// getters and setters
}
PrimeFaces extracts the constraints for @Size via org.primefaces.validate.bean.SizeClientValidationConstraint,
like below:
package
org.primefaces.validate.bean;
import
java.util.HashMap;
import
java.util.Map;
import javax.validation.constraints.Size;
import
javax.validation.metadata.ConstraintDescriptor;
import
org.primefaces.util.HTML;
public class
SizeClientValidationConstraint implements ClientValidationConstraint {
private static final String MESSAGE_METADATA =
"data-p-size-msg";
private static final String MESSAGE_ID = "{javax.validation.constraints.Size.message}";
public Map<String, Object>
getMetadata(ConstraintDescriptor constraintDescriptor) {
Map<String, Object> metadata = new
HashMap<String, Object>();
Map attrs =
constraintDescriptor.getAttributes();
Object message =
attrs.get("message");
metadata.put(HTML.VALIDATION_METADATA.MIN_LENGTH,
attrs.get("min"));
metadata.put(HTML.VALIDATION_METADATA.MAX_LENGTH,
attrs.get("max"));
if (!message.equals(MESSAGE_ID)) {
metadata.put(MESSAGE_METADATA, message);
}
return metadata;
}
public String getValidatorId() {
return Size.class.getSimpleName();
}
}
Now, the extracted constrains are used in beanvalidation.js, as below:
if
(window.PrimeFaces) {
...
PrimeFaces.locales.en_US.messages["javax.validation.constraints.Size.message"]
= "size must be between {0} and {1}";
PrimeFaces.validator.Size = {
MESSAGE_ID:
"javax.validation.constraints.Size.message",
validate: function(d, f) {
if (f !== null) {
var e = d.val().length,
c = d.data("p-minlength"),
a = d.data("p-maxlength"),
b =
PrimeFaces.util.ValidationContext;
if (e < c || e > a) {
throw b.getMessageBV(d, this.MESSAGE_ID,
d.data("p-size-msg"), c, a)
}
}
}
};
...
};
So, this will produce the error messages from figure below:
Now, let's suppose that we want to change this message and involve more information in it. For example, let's suppose that we want to provide in the error messages the labels of the invalid components. So, instead of the above image, we want to obtain something like this:
Note In case of server-side validation via Bean Validation, you can accomplish this task via OmniFaces JsfLabelMessageInterpolator.
In order to accomplish this task we have several approaches. One of
these approaches consist in overriding the SizeClientValidationConstraint for extracting
the validated input label and overriding the client-side implementation to take
this label into account.
So, first we will write a new SizeClientValidationConstraint like below:
import
java.util.HashMap;
import
java.util.Map;
import
javax.validation.constraints.Size;
import
javax.validation.metadata.ConstraintDescriptor;
import static
org.omnifaces.util.Components.getCurrentComponent;
import static
org.omnifaces.util.Components.getLabel;
import
org.primefaces.util.HTML;
public class
SizeClientValidationConstraint implements ClientValidationConstraint {
private static final String MESSAGE_METADATA =
"data-p-size-msg";
private static final String MESSAGE_ID =
"{javax.validation.constraints.Size.message}";
public Map<String, Object>
getMetadata(ConstraintDescriptor constraintDescriptor) {
Map<String,
Object> metadata = new HashMap<String, Object>();
Map
attrs = constraintDescriptor.getAttributes();
Object
message = attrs.get("message");
metadata.put(HTML.VALIDATION_METADATA.MIN_LENGTH,
attrs.get("min"));
metadata.put(HTML.VALIDATION_METADATA.MAX_LENGTH,
attrs.get("max"));
metadata.put(HTML.VALIDATION_METADATA.LABEL,
getLabel(getCurrentComponent()));
if (!message.equals(MESSAGE_ID))
{
metadata.put(MESSAGE_METADATA, message);
}
return
metadata;
}
public String getValidatorId() {
return Size.class.getSimpleName();
}
}
Thanks to OmniFaces utilities, we can obtain the label of the current
validated input component via Components#getCurrentComponent()
and Components#getLabel().
This save us for writing a good chunk of code! Further, we simply add the label
in the metadata under HTML.VALIDATION_METADATA.LABEL.
Now, on client-side, we adjust the JavaScript code to use this label in
error validation messages for @Size:
<script
type="text/javascript">
//<![CDATA[
PrimeFaces.locales.en_US.messages["javax.validation.constraints.Size.message"]
= "The size of {0} must be between {1} and {2} characters";
PrimeFaces.validator.Size = {
MESSAGE_ID:
"javax.validation.constraints.Size.message",
validate: function (d, f) {
if (f !== null) {
var e = d.val().length,
c = d.data("p-minlength"),
a = d.data("p-maxlength"),
b =
PrimeFaces.util.ValidationContext;
if (e < c || e > a) {
throw b.getMessageBV(d, this.MESSAGE_ID,
d.data("p-size-msg"), l, c, a)
}
}
}
};
//]]>
</script>
Done! The complete application in available here.
Read more such goodies in:
Read more such goodies in:
Niciun comentariu :
Trimiteți un comentariu