Reputation: 1458
We are currently creating a couple of input fields which will contain a start and end datetime, one in each field. We have validation currently working so that it displays an error message if a user puts the start time after the end time (and vice verse for an end time before the start) however we have come across an interesting issue with this.
If the user, for example, puts an end time before the start time, we get an error message on the end time as expected.
However if the start date is then amended as opposed to the end date, the message remains.
Is there a way to remove/update/correct the validation message on a different field? Here's the code for the validation:
[Required(ErrorMessage = "{0} is required!")]
[Display(Name = "Start Date")]
[Remote("IsTestPlanEndCorrect", "Analysis", AdditionalFields = "EndDate", HttpMethod = "Post", ErrorMessage = "Test Plan Start Time must be before End.")]
public System.DateTime StartDate { get; set; }
[Required(ErrorMessage = "{0} is required!")]
[Display(Name = "End Date")]
[Remote("IsTestPlanEndCorrect", "Analysis", AdditionalFields = "StartDate", HttpMethod = "Post", ErrorMessage = "Test Plan End Time must be after Start.")]
public System.DateTime EndDate { get; set; }
IsTestPlanEndCorrect
is simply a method which returns true or false depending if the passed data passes the validation.
EDIT: Razor code for the fields:
<div class="form-group">
@Html.LabelFor(t => t.StartDate, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(t => t.StartDate, new { @class = "form-control datetimepicker", placeholder = "Enter Test Plan Start"})
@Html.ValidationMessageFor(t => t.StartDate)
</div>
</div>
<div class="form-group">
@Html.LabelFor(t => t.EndDate, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(t => t.EndDate, new { @class = "form-control datetimepicker", placeholder = "Enter Test Plan End"})
@Html.ValidationMessageFor(t => t.EndDate)
</div>
</div>
Validation code in the controller:
[HttpPost]
public JsonResult IsTestPlanEndCorrect(DateTime EndDate, DateTime StartDate )
{
return Json(TimeManipulation.checkDate(StartDate,EndDate));
}
Upvotes: 2
Views: 1984
Reputation:
The reason for the behavior is that jquery client side validation is triggered for the element you editing (initially on .blur()
and thereafter on .keyup()
). Changing the value in the StartDate
textbox does not trigger validation of the EndDate
value, it only triggers validation of the StartDate
value, so therefore the validation message does not disappear.
You could solve this by specifically triggering the .keyup()
event in the 'other' textbox, for example
$('#StartDate').change(function() {
$('#EndDate').trigger('keyup'); // or $('#EndDate').valid();
});
$('#EndDate').change(function() {
$('#StartDate').trigger('keyup'); // or $('#StartDate').valid();
});
However using a RemoteAttribute
to check values which are already known in the client is a waste of resources and you would be making a minimum of 2 calls to your database each time you alter the values. In addition, remote validation is client side only and you need to repeat you validation logic again in the POST method and manually add ModelStateError
's to protect against a malicious user.
Instead, use a custom validation attribute that implements IClientValidatable
so that you get both client side and server side validation without the need to ajax calls. For a good guide on implementing your own, refer The Complete Guide To Validation In ASP.NET MVC 3 - Part 2. Or for a ready made solution, consider using foolproof [GreaterThan]
and [LessThan]
validation attributes. Note that typically you apply one or the other to one of the properties, but if you do want to apply it to both, e.g.
[LessThan("EndDate")]
public DateTime StartDate { get; set; }
[GreaterThan("StartDate")]
public DateTime EndDate { get; set; }
then you will still need to trigger the .keyup()
events noted above to make the other message disappear.
Upvotes: 2
Reputation: 11971
You'll probably want to / need to achieve this with jQuery
:
$('#StartDate, #EndDate').change(function() {
$('#StartDate, #EndDate').valid();
});
This will cause the validation to be called for both fields every time there is a change on either field. You will probably want to add some additional checks in this code, for example, if end date is empty, you probably don't want to check it just yet.
Upvotes: 0