1 Answer, 1 is accepted
Please refer to
http://demos.kendoui.com/web/datepicker/rangeselection.html
Regards,
Dimo
Telerik
$(function () {
function checkDates() {
if (startDate.val() != '' && endDate.val() != '') {
if (Date.parse(startDate.val()) > Date.parse(endDate.val())) {
alert('End date should be before start date');
endDate.val(startDate.val());
}
}
}
var startDate = $("#startDate").kendoDatePicker({
change: checkDates
});
var endDate = $("#endDate").kendoDatePicker({
change: checkDates
});
$("#startDate").kendoValidator({
rules: {
date: function (input) {
var d = kendo.parseDate(input.val());
return d instanceof Date;
}
}
});
$("#endDate").kendoValidator({
rules: {
date: function (input) {
var d = kendo.parseDate(input.val());
return d instanceof Date;
}
}
});
});
Can anyone point me the right direction? Thanks.
The online demo works as expected, but uses a different approach, compared to your implementation - each DatePicker change handler limits the range of valid values of the other DatePicker.
@Greg
One option is to use an edit form template
http://docs.kendoui.com/api/web/grid#configuration-editable.template
Another option is to use two custom editors with preset IDs and attach change handlers.
http://demos.kendoui.com/web/grid/editing-custom.html
The best option is probably to use custom validation rules in the model. The following is based on the Grid popup editing demo and defines a dummy requirement that the UnitPrice should be greater than UnitsInStock.
http://demos.kendoui.com/web/grid/editing-popup.html
Note that the custom validation rule is executed for every field, so you first check which field is the current one, and also, return true for the unrelated fields, and true/false for the related fields.
schema: {
model: {
id:
"ProductID"
,
fields: {
ProductID: { editable:
false
, nullable:
true
},
ProductName: { validation: { required:
true
} },
UnitPrice: { type:
"number"
,
validation: {
required:
true
,
min: 1,
custom:
function
(input) {
if
(input && (input.attr(
"name"
) ==
"UnitPrice"
|| input.attr(
"name"
) ==
"UnitsInStock"
)) {
// add custom validation message
input.attr(
"data-custom-msg"
,
"foo"
);
// retrieve widgets
var
unitPriceInput = input.closest(
".k-edit-form-container"
).find(
"[name='UnitPrice']"
).data(
"kendoNumericTextBox"
);
var
unitsInStockInput = input.closest(
".k-edit-form-container"
).find(
"[name='UnitsInStock']"
).data(
"kendoNumericTextBox"
);
// validate
if
(unitPriceInput.value() < unitsInStockInput.value()) {
return
false
;
}
else
{
return
true
;
}
}
// return true for unrelated fields
return
true
;
}
}
},
Discontinued: { type:
"boolean"
},
UnitsInStock: { type:
"number"
, validation: { min: 0, required:
true
} }
}
}
}
Regards,
Dimo
Telerik
I have one more question to refine the validation though. I would like to ignore the time portion of the dates I am comparing.
e.g. 10/01/2013 16:00:00 is technically less than 10/01/2013 17:00:00, but I want to simply compare 10/01/2013 and 10/01/2013 and determine them to be equal (and fail the test in my code below).
This is the field definition I have running. This works except it includes the time in the comparison.
contractStartDate: {
type: "date", validation: {
validateContractStartDate: function (input) {
// Check that input field is the one we want to validate. This fires for every field.
if (input && (input.attr("name") == "contractStartDate")) {
// Retrieve widgets.
var contractEndDateInput = input.closest(".k-edit-form-container").find("[name='contractEndDate']").data("kendoDatePicker");
var contractStartDateInput = input.closest(".k-edit-form-container").find("[name='contractStartDate']").data("kendoDatePicker");
// Validate
var s = contractStartDateInput.value();
var e = contractEndDateInput.value();
if (e <= s) {
input.attr("data-validateContractStartDate-msg", "Start Date must be earlier than End Date");
return false;
} else
return true;
} else
// return true for unrelated fields
return true;
}
}
},
contractEndDate: {
type: "date", validation: {
validateContractEndDate: function (input) {
// Check that input field is the one we want to validate. This fires for every field.
if (input && (input.attr("name") == "contractEndDate")) {
// Retrieve widgets.
var contractEndDateInput = input.closest(".k-edit-form-container").find("[name='contractEndDate']").data("kendoDatePicker");
var contractStartDateInput = input.closest(".k-edit-form-container").find("[name='contractStartDate']").data("kendoDatePicker");
// Validate
var s = contractStartDateInput.value();
var e = contractEndDateInput.value();
if (e <= s) {
input.attr("data-validateContractEndDate-msg", "End Date must be later than Start Date");
return false;
} else
return true;
} else
// return true for unrelated fields
return true;
}
}
},
You have two standard Javascript Date objects. How should you compare them while ignoring the time portions?
Dimo
Telerik
var s = contractStartDateInput.value();
var e = contractEndDateInput.value();
var s1 = new Date(s.toDateString());
var e1 = new Date(e.toDateString());
if (e1 <= s1) {
I found that the demo code did work - beautifully! As soon as a date is selected in the first datepicker, the second datepicker only shows dates for the day after that.
I used the javascript verbatim from the demo on the following view code:
@(Html.Kendo().DatePickerFor(m => m.main.LeaveStart)
.Name("start")
.Events(e => e.Change("startChange"))
)
@(Html.Kendo().DatePickerFor(m => m.main.LeaveEnd)
.Name("end")
.Events(e => e.Change("endChange"))
)
Correction to my post of 3 hours ago - since my DatePicker is bound to a data model, using the .Name property causes an error. For the View all I need is:
@(Html.Kendo().DatePickerFor(m => m.main.LeaveStart)
.Events(e => e.Change("startChange"))
)
and similar for LeaveEnd.
And for the JavaScript part, it is as in http://demos.telerik.com/aspnet-mvc/datepicker/rangeselection
but with
var endPicker = $("#main_LeaveStart").data("kendoDatePicker"),
instead of
var endPicker = $("#end").data("kendoDatePicker"),
Hi,
I have the same issue, I use the function change in the date-pickers and it's great.
but also I want to validate it when the user enter a date by writing or pasting.
how do I need to do it through the kendo validation?
my html
@using (Ajax.BeginForm("SaveNewProject", "Project", new AjaxOptions { OnSuccess = "onProjectSuccess" }, new { id = "projectForm" }))
{
<div class="form-horizontal" id="tempPage" style="margin-top:20px">
@Html.AntiForgeryToken()
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.ProductID)
<div class="form-group" id="tempPage">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-6 col-sm-6">
@Html.Kendo().TextBoxFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group" id="tempPage">
@Html.LabelFor(model => model.CodeReviewerID, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-6 col-sm-6">
@(Html.Kendo().DropDownListFor(model => model.CodeReviewerID)
.Name("CodeReviewerID")
.HtmlAttributes(new { style = "width:220px;" })
.OptionLabel("Select Code Reviewer...")
.DataValueField("ID")
.DataTextField("Name")
.BindTo(Model.Developers))
@Html.ValidationMessageFor(model => model.CodeReviewerID, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group" id="tempPage">
@Html.LabelFor(model => model.LeaderID, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-6 col-sm-6">
@(Html.Kendo().DropDownListFor(model => model.LeaderID)
.Name("LeaderID")
.HtmlAttributes(new { style = "width:220px;" })
.OptionLabel("Select Leader...")
.DataValueField("ID")
.DataTextField("Name")
.BindTo(Model.Developers))
@Html.ValidationMessageFor(model => model.LeaderID, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group" id="tempPage">
@Html.LabelFor(model => model.ActualStartDate, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-6 col-sm-6">
@(Html.Kendo().DatePickerFor(model => model.ActualStartDate)
.Name("ActualStartDate")
.Format("MM/dd/yyyy")
.Value(DateTime.Now)
.Events(e => e.Change("startChangeActual").Open("startActualOpen")))
@Html.ValidationMessageFor(model => model.ActualStartDate, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group" id="tempPage">
@Html.LabelFor(model => model.ActualEndDate, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-6 col-sm-6">
@(Html.Kendo().DatePickerFor(model => model.ActualEndDate)
.Name("ActualEndDate")
.Format("MM/dd/yyyy")
.Value(DateTime.Now)
.Events(e => e.Change("endChangeActual").Open("endActualOpen")))
@Html.ValidationMessageFor(model => model.ActualEndDate, "", new { @class = "text-danger" })
</div>
</div>
<div class="container-fluid" style="padding-top:10px">
<hr id="newProjectHR" />
</div>
<div id="buttonPanel">
<input type="submit" value="save" class="k-button" id="btn_save_project" />
</div>
</div>
}
my js:
$(function () {
var validator = $("#projectForm").kendoValidator().data("kendoValidator");
});
function startChangeActual() {
var endPicker = $("#ActualEndDate").data("kendoDatePicker"),
startDate = this.value();
if (startDate) {
startDate = new Date(startDate);
startDate.setDate(startDate.getDate());
endPicker.min(startDate);
}
}
function endChangeActual() {
var startPicker = $("#ActualStartDate").data("kendoDatePicker"),
endDate = this.value();
if (endDate) {
endDate = new Date(endDate);
endDate.setDate(endDate.getDate());
startPicker.max(endDate);
}
}
thanks
Currently, this can be achieved with a custom logic on the change event of the DatePicker. It will require subscribing to the paste event of the input element as this will provide the needed information.
I made a Dojo example demonstrating how this can be achieved:
https://dojo.telerik.com/eyaYAT
I hope this is helpful.
Regards,
Stefan
Progress Telerik