martes, 22 de noviembre de 2011
Los mensajes de error asociados a cada validador son almacenados inicialmente en atributos
data-val-*
sobre el control a comprobar, y cuando se detecta un problema de validación, son mostrados copiando su contenido al interior de la etiqueta <span>
que el helper Html.ValidationMessage()
habrá generado sobre la página.Sin embargo, al hilo de una consulta reciente en los foros de ASP.NET MVC en MSDN, perfectamente contestada por el amigo Eduard Tomás, pensé que realmente tenemos poco control sobre cómo se muestran estos errores, así que me he puesto un rato a ver cómo podíamos conseguir introducir lógica personalizada en este punto aprovechando la flexibilidad que ofrece jQuery validate 1.9.
Salvo por la escasez de documentación de este componente, tomar el control en el momento de mostrar los mensajes de error es bastante sencillo. Basta con establecer una función en la propiedad
showErrors
de los settings
del plugin, cosa que podemos hacer con el siguiente script de inicialización:<script type="text/javascript">
$(function () {
var settings = $.data($('form')[0], 'validator').settings;
settings.showErrors = function (errorMap, errorList) {
// Aquí el código personalizado:
[...]
// Y si nos interesa, finalmente podemos
// ejecutar el comportamiento por defecto
this.defaultShowErrors();
};
});
</script>
(Por simplificar, estamos asumiendo que en el formulario hay un único tag <form>
, que es el que capturamos con el selector).La función
showErrors()
recibe dos parámetros. El primero es un “mapa” donde asociamos a cada clave (nombre del campo) el mensaje de error que tenga asociado. Así, por ejemplo, el valor de errorMap.Nombre
será nulo si el campo “Nombre
” del formulario no tiene ningún error (ha validado correctamente), o el texto del error en caso contrario.En el segundo parámetro de la función encontraremos un array con los errores a mostrar. En cada elemento tendremos disponible la propiedad
element
, desde la que podemos acceder al control que ha generado el error, y message
, donde podemos consultar o establecer la descripción del mismo.Es importante tener en cuenta que la función
showErrors()
es invocada con mucha frecuencia durante el proceso de edición (pérdida de foco, obtención de foco, pulsación de teclas…), por lo que desde el punto de vista de la usabilidad no tiene demasiado sentido introducir en ella procesos bloqueantes (como puede ser un alert()
) o demasiado largos en el tiempo, para evitar que se solapen.Por ejemplo, en el siguiente código utilizamos el efecto “highlight” de jQuery UI para resaltar con un rápido destello el elemento en el que se ha detectado un error:
settings.showErrors = function (errorMap, errorList) {
for (var i = 0; i < errorList.length; i++) {
var error = errorList[i];
// error.element es el elemento que ha provocado el error
$(error.element).effect("highlight", { times: 1 }, 100);
}
this.defaultShowErrors();
};
En fin, algo no demasiado útil ;-P, pero interesante en cualquier caso para profundizar un poco en los misterios e interioridades de jQuery validate.Publicado en Variable not found.
Publicado por José M. Aguilar a las 10:33 a. m.
Nadie ha comentado la entrada, ¿quieres ser el primero?
Etiquetas: aspnetmvc, jquery, scripting, trucos, validadores
martes, 15 de noviembre de 2011
No es algo excesivamente frecuente, pero en ocasiones podemos necesitar limpiar el valor de un campo de tipo
O dicho de otra forma, imaginemos la siguiente porción de un formulario en pantalla, que podría ser generada con el código que podéis ver justo a continuación:

Y la pregunta en este momento sería, ¿qué código deberíamos implementar en la función
Aunque de forma intuitiva podría parecer que basta con establecer el valor del campo a una cadena vacía, una prueba rápida nos demostrará que esto no es posible. Desde hace ya tiempo, por motivos de seguridad, los navegadores no permiten el acceso de escritura a la propiedad value en los campos de envío de archivos, por lo que nos encontramos una vía sin salida. Esto lo vemos con el siguiente código, utilizando jQuery:
Como vemos, somos vilmente ignorados cuando intentamos establecerle un valor.
Pues bien, una posible solución consiste en eliminar del DOM el elemento
Y eso es todo :-). Observad que lo único que hacemos es crean un clon del elemento original cuyo
Si queremos generalizar este código e implementar esta funcionalidad de forma no intrusiva podríamos hacer lo siguiente:
Este código añade automáticamente un botón “Limpiar” a continuación de todos los
Espero que os sea de utilidad.
Publicado en: Variable not found.
file
(el que usamos para hacer los uploads) de un formulario, por ejemplo, para evitar que el usuario envíe un archivo que por cualquier motivo no deba ser subido al servidor.O dicho de otra forma, imaginemos la siguiente porción de un formulario en pantalla, que podría ser generada con el código que podéis ver justo a continuación:
<label for="archivo">Archivo a enviar:</label> <input type="file" id="archivo" name="archivo" /> <input type="button" onclick="limpiarInputFile('archivo');" value="Limpiar" />
Y la pregunta en este momento sería, ¿qué código deberíamos implementar en la función
limpiarInputFile()
que estamos utilizando en el evento onclick
si quisiéramos limpiar o inicializar el contenido del campo archivo
?Aunque de forma intuitiva podría parecer que basta con establecer el valor del campo a una cadena vacía, una prueba rápida nos demostrará que esto no es posible. Desde hace ya tiempo, por motivos de seguridad, los navegadores no permiten el acceso de escritura a la propiedad value en los campos de envío de archivos, por lo que nos encontramos una vía sin salida. Esto lo vemos con el siguiente código, utilizando jQuery:
function limpiarInputfile(id) {
var input = $('#' + id);
var nuevoValor = "c:\\windows\\system32\\mspaint.exe";
alert(input.val()); // Muestra "C:\Datos.dat"
input.val(nuevoValor); // Establecemos un nuevo valor
alert(input.val()); // ¡¡Muestra "C:\Datos.dat"!!
}
Como vemos, somos vilmente ignorados cuando intentamos establecerle un valor.
Pues bien, una posible solución consiste en eliminar del DOM el elemento
<input type="file">
y volver a crearlo justo después en el mismo lugar. He visto por ahí varias implementaciones que obligaban a introducir este elemento dentro de un contenedor, pero he creado otra que creo que es más sencilla e igual de efectiva: function limpiarInputfile(id) {
var input = $('#' + id);
var clon = input.clone(); // Creamos un clon del elemento original
input.replaceWith(clon); // Y sustituimos el original por el clon
}
Y eso es todo :-). Observad que lo único que hacemos es crean un clon del elemento original cuyo
value
por supuesto estará en blanco (recordad que esta propiedad no se puede establecer), y justo a continuación eliminamos el elemento original sustituyéndolo por este clon.Si queremos generalizar este código e implementar esta funcionalidad de forma no intrusiva podríamos hacer lo siguiente:
$(function () {
$("input[type=file]").after(
"<input type='button' class='limpiar-inputfile' value='Limpiar'>"
);
$(".limpiar-inputfile").click(function () {
var input = $(this).prev("input[type=file]");
var clon = input.clone();
input.replaceWith(clon);
return false;
});
});
Este código añade automáticamente un botón “Limpiar” a continuación de todos los
<input type=file>
de la página, implementando en el manejador del evento click
la lógica de inicialización del componente que hemos visto antes. De esta forma, sólo se introducirá en la página el botón de limpiado cuando estén activados los scripts, que es en el único momento en que su ejecución tendrá sentido con la solución propuesta.Espero que os sea de utilidad.
Publicado en: Variable not found.
lunes, 14 de noviembre de 2011
Desde aquí, dar la gracias a la organización y a todos los asistentes que han vuelto a conseguir que este evento sea una experiencia inolvidable.
Y para volver poco a poco a la normalidad, estos son los enlaces publicados en Variable not found en Facebook y Twitter del 7 al 10 de noviembre de 2011. Quizás poquitos en comparación con otras veces, pero espero que os resulten igualmente interesantes. :-)
- Libro gratuito sobre Windows Azure
Ibon Landa - Secure Strings in .NET
Abhishek Goenka - Auto wiring parts in ASP.NET MVC with MEF 2
Per Ökvist - ASP.NET MVC: Converting business objects to select list items
Gunnar Peipman - Need a fake repository in your ASP.NET MVC applications? Try DevMagicMake
Vía @MarteenBalliau - Lazy Loading jQuery Tabs with ASP.NET
Mike Brind - Useful Visual Studio Extension - Web Essentials from Mads Kristensen
Scott Hanselman (vía @osotorrio) - Creating static methods at runtime
Filip Ekbergs - [Webcast] Inyección de Dependencias en ASP.NET
Auges - Exploring JavaScript’s Logical OR Operator
Addy Osmani - Cómo crear código inmantenible (o un modo rastrero de volverse imprescindible)
Juan Botías - ASP.NET MVC3: Incoherencias en el tratamiento de doubles
Eduard Tomás - Glimpse 0.86 Released
Anthony van der Hoorn - Changing Your Website Theme based on the Users Language or Culture
Steven Moseley - C#/.NET Little Wonders: The Generic Action Delegates
James Michael Hare - jQuery 1.7 Released – Event handling in a better, simplified and consolidated way
John Petersen
Publicado en: Variable not found
martes, 8 de noviembre de 2011
Required
o StringLength
no las definíamos a nivel de código mediante atributos, sino en el archivo de configuración, lo que podía aportar interesantes ventajas vistas a flexibilizar nuestras soluciones.En este post vamos a ver un nuevo ejemplo de cómo utilizar el mismo mecanismo de proveedores, pero esta vez para conseguir de forma muy sencilla simplificar el código de clases del modelo en las que todas sus propiedades sean por defecto obligatorias, salvo aquellas en las que indiquemos expresamente lo contrario.
lunes, 7 de noviembre de 2011
Estos son los enlaces publicados en Variable not found en Facebook y Twitter del 1 al 6 de noviembre de 2011. Espero que os resulten interesantes. :-)
Publicado en: Variable not found
- Desplegar aplicación web en Azure en 30 segundos
José Perona - jQuery 1.7 Released
jQuery Team - [Debate] ¿Debería tener C# referencias const?
Eduard Tomás - ¿Cuánto ocupan mis tablas y mis índices en Sql Azure (y no Azure)?
Rodrigo Corral - Del software y sus estimaciones: Los puntos de función
Äntonio (!) - Expanding Text Areas Made Elegant
Neil Jenkins - Better Web Forms with HTML5 Forms
Brandon Satrom - Manage Project Libraries with NuGet
Phil Haack - EF 4.2 Released
ADO.NET Team, vía Juan Carlos González - Visual Studio Async CTP (Version 3) Released
Greg Duncan - HTML5 History in IE10
IEBlog - T4MVC with separate view and controller projects
Geoff Hudick - Inner Fields and Lazy Initialization in C#
Steve Smith - Web Forms Model Binding Part 3: Updating and Validation (ASP.NET 4.5 Series)
Scott Guthrie - .NET Framework 4 Now Supports LocalDB
Abel Avram - Libro gratuito: Eloquent JavaScript: A Modern Introduction to Programming
Marijn Haverbeke - NuGet Package of Week #11 - ImageResizer enables clean, clear image resizing in ASP.NET
Scott Hanselman - Consultas para mejorar el rendimiento de tu SQL Azure (y no Azure)
Rodrigo Corral - Create a custom property for tagging content
Brickpile - ASP.NET MVC with PAjax or PushState/ReplaceState and Ajax
Kazi Manzur Rashid - Sharing session between ASP Classic and ASP.NET using ASP.NET Session state server
Li Chen - Tres monos, diez minutos
José Manuel Alarcón - Donut Hole Caching In ASP.NET MVC by Using Child Actions and OutputCacheAttribute
Tugberk Ugurlu
Publicado en: Variable not found
miércoles, 2 de noviembre de 2011
Estos son los enlaces publicados en Variable not found en Facebook y Twitter del 24 al 31 de octubre de 2011. Espero que os resulten interesantes. :-)
Publicado en: Variable not found
- Lessons From A Review Of JavaScript Code
Addy Osmani (Vía @Etnassoft) - Top Ten Idea Killers in Software Development
Navneeth Mandavilli - Unity 3.0 for .NET4.5 Preview
Microsoft Patterns & Practices - Javascript in the small
Ola Bini - C#/.NET Little Wonders: The Complete Collection
James Michael - C# As A Scripting Language In Your .NET Applications using Roslyn
Anoop Madhusudanan - Uso de POST en ASP.NET MVC
Eduard Tomás - Curso de programación con HTML5, CSS3 y JavaScript (I) en DNM+
DNN+, vía Marc Rubiño - Exposing the C# and VB compiler’s code analysis
MSDN, vía Jorge Serrano - Additional HTTP status codes
IETF - Windows Azure: Startup task or OnStart(), which to choose?
Avkash Chauhan - Using HTML5 input types in ASP.NET
Bipin Joshi, vía Óscar Sotorrío - Patterns/Antipatterns/UML/Refactoring
Source Making - Moving to Azure: Worker Roles for Nothing and Tasks for Free
Michael C. Neel - Demystifying jQuery 1.7′s $.Callbacks
Addy Osmani - You have blank page when you run an asp.net mvc site in Azure Compute emulator
Nicolas Humann - Roslyn CTP is available
Patrick Smacchia - Regular Expressions with Timeout in .NET 4.5
Abhishek Sur - Coordinating multiple ajax requests with jquery.when
Joshua Flanagan
Publicado en: Variable not found