Knockout binding to a date picker - javascript

I'm trying to pass the selected date from a Bootstrap date picker to Javascript code. Plus by default, the date picker should select today's date.
Currently, when clicking the search button, the current date is shown in the alert. However, I'm having trouble actually binding it to the date picker. What am I missing/doing wrong?
Date picker code:
<form class="form form-horizontal" style="background-color:white">
<div class="form-group">
<div class="col-lg-2">
<div class="input-group addon">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
<input id="searchDate" readonly style="cursor: pointer;" data-bind="datePicker: SearchDate" class="form-control pad-bottom-when-small" type="text" data-provide="datepicker" data-date-format="dd/mm/yyyy" data-date-autoclose="true"/>
</div>
</div>
<div class="col-lg-3">
<button class="btn btn-success" onclick="search()">Search</button>
</div>
</div>
</form>
My attempt to data bind:
<script>
ko.applyBindings({
SearchDate: ko.observable(moment().toDate()),
});
</script>
<script type="text/javascript">
self.SearchDate = ko.observable(moment().toDate());
function search() {
alert(self.SearchDate());
}
</script>

It seems that you require some reading up on the knockout-side, specifically on the custom binding handler section, it is -a- way of hooking up non-knockout code with your knockout viewmodel in a clean manner. This also creates a reusable piece of code should you need the calendar picker in another part of your application. I've created a very basic concept of what you will require, as an exercise I'll let you sort out the error-handling when entering false dates, or maybe try to come up with an idea where you could implement the addition of having an empty/null input box.
ko.bindingHandlers.datePicker = {
init: function(element, valueAccessor, allBindingsAccessor) {
var options = { format: 'dd-mm-yyyy', weekStart: 1, autoclose: true };
$(element).datepicker(options);
$(element).datepicker().on('changeDate', function(e) { valueAccessor()(e.date); });
},
update: function(element, valueAccessor, allBindingsAccessor) {
var date = ko.unwrap(valueAccessor());
$(element).datepicker('setDate', date);
}
};
ko.applyBindings(() => {
var self = this;
self.foo = ko.observable(new Date());
self.bar = ko.computed(() => {
var date = self.foo();
return date.getDate() + '-' + (date.getMonth() + 1) + '-' + date.getFullYear();
});
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/css/bootstrap-datepicker.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/js/bootstrap-datepicker.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<input type="text" data-bind="datePicker: foo" />
<div data-bind="text: bar"></div>

Related

Getting instance and field id of jQuery Datepicker

I've found a bunch of similar questions for this issue but none of their answers seems to work here. I have a Datepicker in a website where the input of a date is checked when the user is typing. It works well but I also want to have the date colored in realtime when the input is not valid. For that I need the id of the input field the Datepicker is associated with.
When using onClose function in Datepicker definiton, I get inst which is the instance of the current Datepicker object and by inst.id I get the field name. But this does not work in the parseDate function. I also can't pass on inst or make it global, because onClose is never executed before parseDate. I tried $(this).attr('id') as suggested somewhere but it returns undefined. My code (minimal example):
document.addEventListener("DOMContentLoaded", function () {
$(function () {
$(".dp").datepicker({
showOn: "focus",
showMonthAfterYear: false,
dateFormat: "dd.mm.yy",
onClose: function (dateText, inst) {
console.log("field name : ", inst.id); //works, inst.id is 'startDate'.
$("#" + inst.id + ".form-control.dp.hasDatepicker").css("color", "red"); //works, inst.id is 'startDate'.
}
});
$.datepicker.parseDate = function (format, value, settings) {
var field = $(this).attr("id"); //not working, field is null.
$("#" + field + ".form-control.dp.hasDatepicker").css("color", "red"); //not working, field is null.
};
});
});
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div class="row">
<label class="col-sm-3 col-form-label">{{ __('Start') }}</label>
<div class="col-sm-9">
<div class="input-group-addon">
<input type="text" class="form-control dp" id="startDate" name="start" value="">
<span class="glyphicon glyphicon-th"></span>
</div>
</div>
</div>
I would perform the date validity with a input event handler aside the date picker... Because that date check you wish to have is not a feature of datepicker.
So on input, evaluate the new Date value to add an .invalid class to the input like below:
$(document).ready(function () {
$(".dp").datepicker({
showOn: "focus",
showMonthAfterYear: false,
dateFormat: "dd.mm.yy"
});
$(".dp").on("input", function () {
// Remove the class on each new input
$(this).removeClass("invalid");
let currentVal = $(this).val();
console.log(currentVal);
// Split the value
let dateParts = currentVal.split(".");
// If incomplete
if (dateParts.length !== 3) {
$(this).addClass("invalid");
return;
}
// Create a date object to evaluate
let validDate = new Date(`${dateParts[2]}-${dateParts[1]}-${dateParts[0]} 00:00:00`);
console.log(validDate.toString());
// If the date is "invalid" and does not have 4 digits for the year (because it could be valid anyway... But obviously wrong)
if (validDate.toString() === "Invalid Date" || dateParts[2].length !== 4) {
$(this).addClass("invalid");
}
});
});
.dp.invalid{
color: red !important;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div class="row">
<label class="col-sm-3 col-form-label">{{ __('Start') }}</label>
<div class="col-sm-9">
<div class="input-group-addon">
<input type="text" class="form-control dp" id="startDate" name="start" value="">
<span class="glyphicon glyphicon-th"></span>
</div>
</div>
</div>
CodePen

Different action on several DatePicker

I currently have a form in which there is 2 datePicker (Jquery UI).
On the first one, when I "mouseenter" a date, I do an AJAX call to get a response (and it works).
The problem here is that the AJAX call works for both the datePicker. I want it for the first one only!
Here is the HTML :
<div class="item form-group">
<label class="control-label col-md-3 col-sm-3 col-xs-12">Next relaunch</label>
<div class="col-md-6 col-sm-6 col-xs-12" id ="nextLaunchDate">
<input name="nextLaunchDate" class="datePicker form-control col-md-7 col-xs-12" title="Next relaunch">
</div>
</div>
<div class="item form-group">
<label class="control-label col-md-3 col-sm-3 col-xs-12">Validity date</label>
<div class="col-md-6 col-sm-6 col-xs-12">
<input name="validityDate" class="datePicker form-control col-md-7 col-xs-12" title="Validity date">
</div>
</div>
In fact, it's quite basic. Now, here's the JS:
$(document).ready(function() {
$(function () {
$(".datePicker").datepicker({
showWeek: true,
dateFormat: "dd-mm-yy"
});
});
$("body").on("mouseenter", ".ui-state-default", function () {
var element = $(this);
var day = (0 + "" + $(this).text()).slice(-2);
var month = $(this).parent().attr("data-month");
month++;
month = (0 + "" + month).slice(-2);
var date = day + "/" + month + "/" + element.parent().attr("data-year");
$(this).attr('title', date);
$.ajax({
url: '/offer/getrelaunchthatday',
type: 'POST',
data: 'dateSelected=' + day + "-" + month + "-" + element.parent().attr("data-year"),
dataType: 'json',
success: function (json_response) {
if (json_response.status === "success") {
element.attr('title', "Offers today : "+json_response.value);
}
else {
$(".x_panel:first").before("<div class=\"alert alert-danger deletable\">An error happened : <br/>" + json_response.value + "</div>");
}
},
error: function (result, status, error) {
$(".x_panel:first").before("<div class=\"alert alert-danger deletable\">An error happened: <br/>" + error+ "</div>");
}
});
});
});
I understand why the ajax call works for both of the datePicker but I can't understand how I can do the call only for the second one.
If you have any idea about this, don't hesitate to comment! Also, if you have any note on my code, tell me! :)
Have a good day!
EDIT : Here's a codePen to show you my problem : https://codepen.io/anon/pen/aLmpbN
Since jQuery use same date picker component for both inputs, you should add conditional checks using ids. See the following example where two date pickers have different actions when mouseover.
var datePicker = "";
//First date picker
$("#first_date").datepicker({
beforeShow: function() {
datePicker = "FIRST_DATE";
},
onClose: function() {
datePicker = "";
}
});
//Second date picker
$("#second_date").datepicker({
beforeShow: function() {
datePicker = "SECOND_DATE";
},
onClose: function() {
datePicker = "";
}
});
//Add conditional mouse hover events
$("body").on("mouseenter", ".ui-state-default", function() {
if (datePicker == "FIRST_DATE") {
//Do first date picker stuff
console.log("on first date picker");
} else {
//Do second date picker stuff
console.log("on second date picker");
}
});
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
</script>
</head>
<body>
<p>First Date:
<input type="text" id="first_date">
</p>
<p>Second Date:
<input type="text" id="second_date">
</p>
</body>
</html>
You should use ids rather than using a class name for different date inputs.
Just umm...
There is no answer.
It is just your choice. ! :)
<input type="text" id="first_date" class="datePicker" data-type="test1">
<input type="text" id="second_date" class="datePicker" data-type="test2">
$(".datePicker").datepicker({
showWeek: true,
dateFormat: "dd-mm-yy"
});
$("body").on("mouseenter", ".datePicker", function(e) {
var type = $(this).data('type');
if (type == 'test1') {
} else {
// test2
}
}
Give the event through the class name.
HTML
<div>
<label class="control-label col-md-3">Next relaunch</label>
<input name="nextLaunchDate" class="datePicker form-control col-md-7" title="Next relaunch">
</div>
<div>
<label class="control-label col-md-3">Validity date</label>
<input name="validityDate" class="datePicker2 form-control col-md-7" title="Validity date">
</div>
JS
$(".datePicker").datepicker({
showWeek: true,
dateFormat: "dd-mm-yy"
});
$(".datePicker2").datepicker({
showWeek: false,
dateFormat: "yy-mm-dd"
});
Otherwise, you can assign an event based on the class name through JQuery.
good day~
You missed "<" in second label. And use current input in your function, not "body"

JQuery UI Date Picker with Angularjs directive getting wrong value

My 2 Date Pickers bind with Angularjs directive. But i validate with java script.
after selecting date it return default date.
Script
<script>
if (datefield.type != "date") { //if browser doesn't support input type="date", initialize date picker widget:
jQuery(function ($) { //on document.ready
$('#start_date').datepicker({
dateFormat: 'yy-mm-dd',
minDate: 0,
onSelect: function (date) {
var date2 = $('#start_date').datepicker('getDate');
date2.setDate(date2.getDate() + 1);
$('#end_date').datepicker('setDate', date2);
//sets minDate to start_date date + 1
$('#end_date').datepicker('option', 'minDate', date2);
}
});
$('#end_date').datepicker({
dateFormat: 'yy-mm-dd',
onClose: function () {
var start_date = $('#start_date').datepicker('getDate');
console.log(start_date);
var end_date = $('#end_date').datepicker('getDate');
if (end_date <= start_date) {
var minDate = $('#end_date').datepicker('option', 'minDate');
$('#end_date').datepicker('setDate', minDate);
}
}
});
});
}
</script>
Html Code
<div class="col-md-5">
<div class="form-group">
<label name="lblOccup1"> Check in</label>
<input type="date" id="start_date" class="form-control" placeholder="Check in" data-ng-model="departuredate"/>
</div>
</div>
<div class="col-md-5">
<div class="form-group">
<label name="lblOccup1"> Check out</label>
<input type="date" id="end_date" class="form-control" placeholder="Check Out" data-ng-model="returndate"/>
</div>
</div>
<div class="col-md-2">
<a class="link_button2" ng-href="#Url.Action("Booking", "home")?Rooms={{rooms}}&Destination={{des}}&DepartureDate={{departuredate}}&ReturnDate={{returndate}}"> Search </a>
</div>
After press search button i get null value to mvc controller.
Search Form
Controller
What is wrong with this code?

Bootstrap datetimepicker select time view mode

Hi I'm working with bootstrap datetimepicker. I'm trying to show select time view after choose date (click on date). Is there any events to open select time view or something else?
If you are using eonasdan datetimepicker you may use the following events:
dpchange in order to test if the user changed the date
click in order to reset the datetimepicker to the default condition (no time selection)
The snippet:
$('#datetimepicker1').datetimepicker().on('dp.change', function(e) {
var currDate = e.date.format('DD/MM/YYYY');
var oldDate = (e.oldDate == null) ? currDate : e.oldDate.format('DD/MM/YYYY');
var sideBySide = $('#datetimepicker1').data("DateTimePicker").options().sideBySide;
if (currDate != oldDate && sideBySide == false) {
$('#datetimepicker1').data("DateTimePicker").sideBySide(true);
}
}).on('click', 'span.input-group-addon', function(e) {
$('#datetimepicker1').data("DateTimePicker").sideBySide(false);
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.min.js"></script>
<link rel="stylesheet" href="https://rawgit.com/Eonasdan/bootstrap-datetimepicker/master/build/css/bootstrap-datetimepicker.min.css">
<script src="https://rawgit.com/Eonasdan/bootstrap-datetimepicker/master/build/js/bootstrap-datetimepicker.min.js"></script>
<div class="container">
<div class="row">
<div class='col-sm-6'>
<div class="form-group">
<div class='input-group date' id='datetimepicker1'>
<input type='text' class="form-control"/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
</div>
</div>

Javascript Date var to Razor DateTime

I have a jquery datepicker in my .NET MVC5 application. I need to convert the javascript Date var to a Razor DateTime var, after a user selects the correct date. Then I can send it back to the controller. Since Razor is server side and javascript client side, how can we solve this? Check out my code below:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-inline">
<h4>Reservation</h4>
<hr />
<div class="form-group">
<p>Date:<input type="text" id="date1" class="datefield" /></p>
<p>Date:<input type="text" id="date2" class="datefield" /></p>
<script type="text/javascript">
$(document).ready(function () {
$("#date1").on('click', function () {
var minDate = $("#date1").val();
})
$("#date2").on('click', function () {
var maxDate = $("#date2").val();
})
});
</script>
#{DateTime minDateCC = DateTime.Now; DateTime maxDateCC = DateTime.Now;}
<script type="text/javascript">
minDate = Date(#minDateCC);
maxDate = Date(#maxDateCC);
</script>
#Html.ActionLink("Show Available Campingspots Per Date", "ShowAvailableSpotsPerDate", new { minDateCC, maxDateCC })
</div>
</div>
}

Categories

Resources