El más importante cosa a tener en cuenta al poner todo esto junto es la pequeña parte de la documentación (que no es muy evidente en la documentación de XVal, que abstrae la llamada a rules("add", options)
en la llamada a xVal.AttachValidator
) para rules("add", options)
(énfasis mío):
Agrega las reglas especificadas y devuelve todas las reglas para la primera elemento emparejado. Requiere que el formulario padre esté validado, es decir, $ ("formulario"). Validate() se llama primero .
Esto es especialmente importante cuando el plugin Formulario jQuery entra en juego, y que desea enviar el formulario a través de AJAX, ya que tienes que configurar una opción submitHandler
en la llamada a validate(options)
, así:
<script type="text/javascript">
$(document).ready(function() {
// Initialize the form. Store the validator.
var validator = $("form").validate({
// Called when the form is valid.
submitHandler: function(form) {
// Submit the form via ajax.
$(form).ajaxSubmit({
// The return data type is json.
dataType: "json",
// The callback on a successful form
// submission.
success: function(data, statusText) {
// If the new location is not null, then
// redirect to that location.
if (data.data.newLocation) {
// Go to the new location.
document.location.href = data.data.newLocation;
// Get out.
return;
}
// There are errors, pass them to the validator
// for display.
validator.showErrors(data.data.errors);
}
});
}
});
});
</script>
Debido a la documentación citada anteriormente en relación con las llamadas a rules("add", options)
, la llamada a validate(options)
debe llegar antes que las llamadas a rules("add", options)
.
Si no lo hacen, entonces el submitHandler se ignora, nunca se llama.
Al final, esto significa que el código del lado del cliente tiene que tener este aspecto cuando se lo ponga todo junto:
<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="jquery.validate.min.js"></script>
<script type="text/javascript" src="jquery.form.js"></script>
<!-- Note this is only needed if using xVal. -->
<script type="text/javascript" src="xVal.jquery.validate.js"></script>
<!-- The call to validate the form must come first. -->
<script type="text/javascript">
$(document).ready(function() {
// Initialize the form.
$("form").validate({
// Called when the form is valid.
submitHandler: function(form) {
// Submit the form via ajax.
$(form).ajaxSubmit({
// The return data type is json.
dataType: "json",
// The callback.
success: function(data, statusText) {
// Alert the users to the message.
window.alert(statusText);
}
});
}
});
});
</script>
<!-- Now make the calls to rules("add", options), AFTER the call to -->
<!-- validate (options). It's separated into another block for -->
<!-- emphasis, but could be done in the block above. -->
<script type="text/javascript">
// Make calls to rules("add", options).
</script>
<!-- Or, if you are using xVal, make the following call in the ASP.NET -->
<!-- page but again, note it must come AFTER the call to -->
<!-- validate(options). -->
<%= Html.ClientSideValidation<Model>("model") %>
Finalmente, con todo esto cableado, lo último que hay que hacer es lo que debe hacer cuando el método del lado del servidor retorna.
Querrás que el JSON que se devuelve de estas llamadas sea algo así como un shell de modelo de vista estandarizado donde tienes el contenido específico de respuesta envuelto en una pieza más estandarizada que expone la información que necesitas a través de llamadas homogéneas, algo como esto :
{
// An integer, non-zero indicates faulure, with predefined ranges
// for standard errors across all operations, with other ranges for custom
// errors which are operation-specific. Examples of shared errors
// are not authenticated, not authorized, etc, etc.
resultCode: 0,
// A string, which is to be displayed to the user (usually in the
// form of a jQuery dialog, usually used for the common ranges of
// errors defined above.
message: null,
// An object with operation-specific results.
data: null
}
para los errores en el servidor, devuelven el mismo que el anterior, pero con una ubicación que tiene la URL, que el usuario debe ser redirigido a el éxito (o nulo si no se ha realizado correctamente) y un mapa que se puede pasar directamente al método showErrors(errors)
si hay errores en los campos:
{
resultCode: 0,
message: null,
data:
{
// Returned as a string. If not null, then this is the url
// that the client should be redirected to, as the server-side
// operation was successful.
newLocation: null,
// If not-null, then this is a map which has the names of the
// fields with the errors, along with the errors for the fields.
errors:
{
"model.title": "The title already exists in the system.",
"model.body": "The body cannot have malicious HTML code in it."
}
}
}
Teniendo en cuenta que, el pasado success
field of the options
parameter a ajaxSubmit
debe quedar claro:
// The callback on a successful form
// submission.
success: function(data, statusText) {
// If the new location is not null, then
// redirect to that location.
if (data.data.newLocation) {
// Go to the new location.
document.location.href = data.data.newLocation;
// Get out.
return;
}
// There are errors, pass them to the validator
// for display.
validator.showErrors(data.data.errors);
}
Todo lo que hace es comprobar para ver si se define la propiedad newLocation
. Si está definido, redirige el documento actual a la ubicación (que normalmente sería la url del recurso recientemente guardado).
Si no se define, entonces toma el mapa y la pasa al showErrors
en el validador devuelto por una llamada a validate(options)
, el establecimiento de los mensajes de error utilizando el posicionamiento y estilo especificado por la llamada a validate(options)
.