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>
}
Related
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
I'm building a sidebar for Google Sheets using Apps Script, it is a tool to import data from Google Calendar. The script is not that complicated:
A form to choose the calendar, a start and end date, and a checkbox to include a header
Some client-side javascript
Some server-side functions
1. I have a file Code.gs in charge of creating a custom menu and rendering the sidebar
function onOpen() {
SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
.createMenu('Custom Menu')
.addItem('Show sidebar', 'showSidebar')
.addToUi();
}
function showSidebar() {
var html = HtmlService.createTemplateFromFile('index').evaluate()
.setTitle('Extract data from calendar')
.setWidth(300);
SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
.showSidebar(html);
}
function include(filename){
return HtmlService.createHtmlOutputFromFile(filename).getContent();
}
2. Index.html: the content of the sidebar
<!DOCTYPE html>
<html>
<head>
</head>
<body style="margin: 10px;">
<!-- Compiled and minified CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<!-- Compiled and minified -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<div class="row">
<form class="col s12">
<!-- CHOOSE CALENDAR ROW -->
<div class="row">
<div class="input-field col s12">
<select id='calendar'>
<? var calendars = CalendarApp.getAllOwnedCalendars();
calendars.forEach((calendar) => { ?>
<option value="<?= calendar.getId() ?>"><?= calendar.getName() ?></option>
<? }) ?>
</select>
<label>Calendar</label>
</div>
</div>
<!-- START TIME ROW -->
<div class="row">
<div class="input-field col s12">
<input placeholder="Start date" id="startDate" type="date" class="validate">
<label for="startDate">Start date</label>
</div>
</div>
<!-- END TIME ROW -->
<div class="row">
<div class="input-field col s12">
<input placeholder="End date" id="endDate" type="date" class="validate">
<label for="endDate">End Date</label>
</div>
</div>
<!-- INCLUDE HEADER -->
<div class="row">
<label>
<input type="checkbox" class="filled-in" checked="checked" id="includeHeader" />
<span>Include Header</span>
</label>
</div>
<!-- EXTRACT BUTTON -->
<div class="row">
<button class="btn waves-effect waves-light" id="extractBtn">EXTRACT</button>
</div>
</form>
</div>
<?!= include('index-js') ?>
<script>
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('select');
var instances = M.FormSelect.init(elems, {});
});
</script>
</body>
</html>
3. index-js.html: add an event to the extract button and call the server-side function
<script>
var extractBtn = document.getElementById('extractBtn');
extractBtn.addEventListener('click', function(e) {
e.preventDefault();
var calendarId = document.getElementById('calendar').value;
var startDate = new Date(document.getElementById('startDate').value);
var endDate = new Date(document.getElementById('endDate').value);
var includeHeader = document.getElementById('includeHeader').checked;
if(startDate.getTime() < endDate.getTime()) {
e.target.textContent = 'Extracting...';
google.script.run.withSuccessHandler(extractCompleted).writeData(calendarId, startDate, endDate, includeHeader);
} else {
M.toast({html: "Please enter an end date starting after the selected start date"});
}
});
function extractCompleted(){
M.toast({html: 'Extract completed'});
extractBtn.textContent = 'Extract';
}
</script>
4. extractCalendar.gs in charge of getting the data and adding it to the Google sheet
function extractCalendar(calendarId, startDate, endDate) {
var calendar = CalendarApp.getCalendarById(calendarId);
var events = calendar.getEvents(startDate, endDate);
// Initialize variables that will hold information
var rows = [];
events.forEach((event) => {
// Get basic information
var eventTitle = event.getTitle();
var startTime = event.getStartTime();
var endTime = event.getEndTime();
var description = event.getDescription();
var isRecurring = event.isRecurringEvent();
// Get the guest list
var guests = event.getGuestList();
var emailsParticipantsArray = [];
var emailsParticipants = '';
// Add each guest email to the array
guests.forEach(guest => emailsParticipantsArray.push(guest.getEmail()));
// Convert the array to a string
emailsParticipants = emailsParticipantsArray.join(',');
rows.push([eventTitle, startTime, endTime, emailsParticipants, description, isRecurring]);
}
);
return rows;
}
function writeData(calendarId, startDate, endDate, includeHeader=True){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var rows = extractCalendar(calendarId, startDate, endDate);
var numRows = rows.length;
var lastRow = sheet.getLastRow();
(includeHeader) && rows.unshift(['Title', 'Start Date', 'End Date', 'Participants Email', 'Description', 'Recurring']);
sheet.getRange(lastRow + 1, 1, numRows, 6).setValues(rows);
}
The line below does not run and generate the error message: Uncaught TypeError: Failed due to illegal value in property: 12769757186-mae_html_user_bin_i18n_mae_html_user.js:61
google.script.run.withSuccessHandler(extractCompleted).writeData(calendarId, startDate, endDate, includeHeader);
What's happening right here, why is the server-side function not running?
Thank you for your help !
Parameters and Return Values
You can pass year,month and day or the date in a standard string format and use the Date() constructor to recreate the date.
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>
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"
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?