jquery - validación - validar correo electronico mvc
Validación personalizada de MVC: compare dos fechas (4)
Debe modificar el script del lado del cliente para verificar el prefijo del elemento probado y agregar el prefijo (si corresponde) a su selector, de la siguiente manera:
$.validator.addMethod("isdateafter", function(value, element, params) {
var parts = element.name.split(".");
var prefix = "";
if (parts.length > 1)
prefix = parts[0] + ".";
var startdatevalue = $(''input[name="'' + prefix + params.propertytested + ''"]'').val();
if (!value || !startdatevalue)
return true;
return (params.allowequaldates) ? Date.parse(startdatevalue) <= Date.parse(value) :
Date.parse(startdatevalue) < Date.parse(value);
});
Creé un ValidationAttribute personalizado que compara 2 fechas y se asegura de que la segunda fecha sea mayor que la primera:
public sealed class IsDateAfter : ValidationAttribute, IClientValidatable
{
private readonly string testedPropertyName;
private readonly bool allowEqualDates;
public IsDateAfter(string testedPropertyName, bool allowEqualDates = false)
{
this.testedPropertyName = testedPropertyName;
this.allowEqualDates = allowEqualDates;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var propertyTestedInfo = validationContext.ObjectType.GetProperty(this.testedPropertyName);
if (propertyTestedInfo == null)
{
return new ValidationResult(string.Format("unknown property {0}", this.testedPropertyName));
}
var propertyTestedValue = propertyTestedInfo.GetValue(validationContext.ObjectInstance, null);
if (value == null || !(value is DateTime))
{
return ValidationResult.Success;
}
if (propertyTestedValue == null || !(propertyTestedValue is DateTime))
{
return ValidationResult.Success;
}
// Compare values
if ((DateTime)value >= (DateTime)propertyTestedValue)
{
if (this.allowEqualDates)
{
return ValidationResult.Success;
}
if ((DateTime)value > (DateTime)propertyTestedValue)
{
return ValidationResult.Success;
}
}
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = this.ErrorMessageString,
ValidationType = "isdateafter"
};
rule.ValidationParameters["propertytested"] = this.testedPropertyName;
rule.ValidationParameters["allowequaldates"] = this.allowEqualDates;
yield return rule;
}
Clase CalendarEntry: ...
public virtual DateTime StartDate { get; set; }
[IsDateAfter("StartDate", true, ErrorMessage="End date needs to be after start date")]
public virtual DateTime EndDate { get; set; }
VER:
$.validator.unobtrusive.adapters.add(
''isdateafter'', [''propertytested'', ''allowequaldates''], function (options) {
options.rules[''isdateafter''] = options.params;
options.messages[''isdateafter''] = options.message;
});
$.validator.addMethod("isdateafter", function(value, element, params) {
alert(params.propertytested);
var startdatevalue = $(''input[name="'' + params.propertytested + ''"]'').val();
if (!value || !startdatevalue) return true;
return (params.allowequaldates) ? Date.parse(startdatevalue) <= Date.parse(value) : Date.parse(startdatevalue) < Date.parse(value);
}, '''');
Esto funciona bien cuando CalendarEntry no está dentro de otra clase. SIN EMBARGO, cuando uso un modelo de vista así:
public class TrainingDateEditViewModel
{
#region Properties
/// <summary>
/// Gets or sets CalendarEntry.
/// </summary>
public CalendarEntry CalendarEntry { get; set; }
....
La validación del cliente ya no funciona porque la salida html producida es la siguiente:
<input type="text" value="" name="CalendarEntry.EndDate" id="CalendarEntry_EndDate" data-val-isdateafter-propertytested="StartDate" data-val-isdateafter-allowequaldates="True" data-val-isdateafter="End date needs to be after start date" data-val="true">
Y el
data-val-isdateafter-propertytested="StartDate" and IT SHOULD BE: "CalendarEntry.StartDate".
¿Cómo podría hacerlo para que se uniera a la regla "CalendarEntry.StartDate". ValidationParameters ["propertytested"] = this.testedPropertyName; // AQUÍ DEBE SER EL NOMBRE COMPLETO ??? ¿¿CÓMO??
Gracias
En la última respuesta, faltaron algunos paréntesis en la llamada a toLowerCase, aquí hay una versión actualizada con el documento listo y la parte $ .validator.unobtrusive ...-:
$(function () {
$.validator.addMethod("isdateafter", function(value, element, params) {
var parts = element.name.split(".");
var prefix = "";
for (var i = 0; i < parts.length - 1; i++) {
prefix = parts[i] + ".";
}
var startdatevalue = $(''input[name="'' + prefix + params.propertytested + ''"]'').val();
if (!value || !startdatevalue) return true;
var allowequal = params.allowequaldates.toLowerCase() === "true";
return allowequal ? Date.parse(startdatevalue) <= Date.parse(value) :
Date.parse(startdatevalue) < Date.parse(value);
});
$.validator.unobtrusive.adapters.add(''isdateafter'',
[''propertytested'', ''allowequaldates''],
function (options) {
options.rules[''isdateafter''] = options.params;
options.messages[''isdateafter''] = options.message;
});
});
No olvide incluir el lado del cliente dentro de este código. ¡Me llevó horas encontrar que esto faltaba!
(function ($) {
// your code here..
})(jQuery);
Solo para corregir un pequeño error en el javascript de counsellorben: el "(params.allowequaldates)" se interpretará como una cadena (que tendrá un valor de "False" o "True"), pero esa cadena siempre se evaluará como verdadera, permitiendo siempre las mismas fechas. Si también desea permitir más niveles de anidación de sus objetos que solo 1, obtendrá:
$.validator.addMethod("isdateafter", function(value, element, params) {
var parts = element.name.split(".");
var prefix = "";
for (var i = 0; i < parts.length - 1; i++)
prefix = parts[i] + ".";
var startdatevalue = $(''input[name="'' + prefix + params.propertytested + ''"]'').val();
if (!value || !startdatevalue)
return true;
var allowequal = params.allowequaldates.toLowerCase === "true";
return allowequal ? Date.parse(startdatevalue) <= Date.parse(value) :
Date.parse(startdatevalue) < Date.parse(value);
});