Use php array to disable dates in datepicker and times in timepicker from onSelect in DatePicker
I have a datepicker input and a time input that I would like to use to assign a person for appointments.
When the user clicks on enter to open the datepicker menu, I would like to gray out specific dates. I have a php function that returns this datetimes array in the format of the string "Ymd H: i: s". But I don't know how to use this function return value to give the javascript function what it needs to disable the date range in the datepicker.
In the onSelect event of my datepicker, I want it to enable / disable the time options in my timepicker, according to which timeslots are booked for that day. But I dont know how.
-
Datepicker uses beforeshowDay: to disable booked dates
-
user selects date from datepicker
-
Datepicker enables / disables time in timepicker
I figured out how to disable timers in the timepicker Here . example code:
$('input.timepicker').timepicker({
'disableTimeRanges': [
['1am', '2am'],
['3am', '4:01am']
]
});
But this is how I will disable the time ranges within the scope of the timepicker. I don't know how to disable them from BeforeShowDay in datepicker?
<script type="text/javascript">
$(document).ready(function(){
$( "#datepickerListAppointments" ).datepicker(
{
minDate:'0',
beforeShowDay:
function(dt)
{ // need to disable days other than tuesday and wednesday too.
return [dt.getDay() === 2 || dt.getDay() === 3, ""];
},
onSelect : function(){
should disable/enable timepicker times from here?
}
});
$('input.timepicker').timepicker({
timeFormat: 'h:mm p',
interval: 90,
minTime: '9',
maxTime: '10:30am',
defaultTime: '9',
startTime: '9:00',
dynamic: false,
dropdown: true,
scrollbar: false
});
});
This is a function that gives data if it helps to know.
function get_next_open_appointments($numAppointments, $timeSlotToExclude = "")
{
global $db;
$whereCondition = "WHERE FirstName = :null ";
if ($timeSlotToExclude != "")
{
$whereCondition .= "AND AppointmentTime != '$timeSlotToExclude' ";
}
$query = "SELECT DISTINCT AppointmentTime FROM appointments
$whereCondition
ORDER BY AppointmentTime ASC LIMIT $numAppointments";
$statement = $db->prepare($query);
$statement->bindValue(':null', "");
$statement->execute();
$datesArray = array();
while ($row = $statement->fetch())
{
array_push($datesArray, $row['AppointmentTime']);
}
$statement->closeCursor();
return $datesArray;
}
UPDATE:
Hugo de Carmo pointed me in the right direction and I got the dates to disable / enable accordingly. However, I don't know how to use the dates I pulled out in the code below to disable / enable the time in the timepicker.
Here's the new code:
<script type="text/javascript">
$(document).ready(function(){
// uses php to get open appointments, and put them in a javascript array
<?php $datetime_openings = get_next_open_appointments(200);
$date_openings = array();
foreach ($datetime_openings as $dt)
{
array_push($date_openings, substr($dt,0,10)); // just the date part
}
$json_date_openings = json_encode($date_openings);
echo "var arr_Openings = ". $json_date_openings . ";\n";
?>
$( "#datepickerOpenAppointments" ).datepicker(
{
minDate:'0',
beforeShowDay:
function(dt)
{
var string = jQuery.datepicker.formatDate('yy-mm-dd', dt);
var bFound = (arr_Openings.indexOf(string) != -1);
return [ bFound ];
},
onSelect : function(){
// Should disable/enable time ranges here?
});
$('input.timepicker').timepicker({
timeFormat: 'h:mm p',
interval: 90,
minTime: '9',
maxTime: '10:30am',
defaultTime: '9',
startTime: '9:00',
dynamic: false,
dropdown: true,
scrollbar: false
});
});
source to share
Try this,
sorry i didn't use beforeshowDay
select date 2017-7-14 and 2017-7-17 and see
var disabledDateTime = {
'2017-7-14':[
['2:30am','3:00am'],
['6:30am','9:00am']
],
'2017-7-17':[
['1:00am','3:00am'],
['5:30am','7:00am'],
['11:30am','2:00pm']
]
};
$(function() {
$('#pickTime').timepicker();
$('#pickDate').datepicker({
'format': 'yyyy-m-d',
'autoclose': true
}).on('changeDate',function(e){
var ts = new Date(e.date);
var m = ts.getMonth()+1;
var dt = ts.getFullYear() + '-' + m + '-' + ts.getDate();
var opt = {'disableTimeRanges': []}
if(typeof(disabledDateTime[dt])!='undefined'){
$('#pickTime').timepicker('setTime', '');
opt = {'disableTimeRanges': disabledDateTime[dt]}
}
$('#pickTime').timepicker('option',opt);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link href="https://jonthornton.github.io/jquery-timepicker/lib/bootstrap-datepicker.css" rel="stylesheet"/>
<script src="https://jonthornton.github.io/jquery-timepicker/lib/bootstrap-datepicker.js"></script>
<link href="https://jonthornton.github.io/jquery-timepicker/jquery.timepicker.css" rel="stylesheet"/>
<script src="https://jonthornton.github.io/jquery-timepicker/jquery.timepicker.js"></script>
<input id="pickDate" type="text" class="date" />
<input id="pickTime" type="text" class="time" />
source to share
Someone has already answered this question here .
Either way, the following code should give you an idea of how to solve the problem.
// supose your script return a json similar to the following
{
"data": [
// ...
"17-07-11"
]
}
$(function() {
$.getJSON("/path/to/script", function(response){
$('#datepickerListAppointments').datepicker({
beforeShowDay: function(dt) {
var config = [];
config[1] = 'class';
if ((dt.getDay() === 2) || (dt.getDay() === 3)) {
config[0] = false;
return config;
}
var string = jQuery.datepicker.formatDate('yy-mm-dd', dt);
config[0] = (response.data.indexOf(string) === -1);
return config;
}
});
});
});
I assumed you are communicating with the server using some kind of API, so use getJSON if you want to handle server errors, I suggest you use ajax concatenating Promise .
Edit 1
You can extract everything from your date using the DateTime class , here is a snippet:
$openings = array();
$date = DateTime::createFromFormat("y/m/d H:i", "17/07/15 08:30");
if (!isset($openings[$date->format("y-m-d")])) {
$openings[$date->format("y-m-d")] = array();
}
$openings[$date->format("y-m-d")][] = array(
"hour" => $date->format("Ha"),
"minute" => $date->format("i")
);
/* result
array(1) {
["17-07-15"]=>
array(1) {
[0]=>
array(2) {
["hour"]=>
string(4) "08am"
["minute"]=>
string(2) "30"
}
}
}
*/
Then you can disable the time in the timepicker based on the date, you will probably need to register a callback function in your datepix to update the timepicker based on the selected date, or you will have to override the timepicker with new settings.
source to share
Yes, you can dynamically update the timepicker disableTimeRanges
inside a function onSelect
using the option
component's timepicker method .
I suppose that:
- You are using jQuery UI datepicker (since you haven't tagged your question with
twitter-bootstrap
andbootstrap-datepicker
hasn'tminDate
) - You are using the first version
get_next_open_appointments
which returns an array of datetimes (['2017-07-25 09:30:00', ...]
see for examplefakeDisabledTimes
in the snippet)
I am using momentjs to make managing dates easier. In the following code, I use the moment parsing functions ( moment(String)
and moment(String, String)
) isSame
, add
and format
. Note that tokens are different from PHP tokens.
Here's a complete working sample:
var fakeDisabledTimes = [
'2017-07-25 09:30:00', '2017-07-26 10:00:00',
'2017-08-01 09:00:00', '2017-08-02 09:30:00',
'2017-08-08 10:30:00', '2017-08-09 10:00:00',
'2017-07-15 09:30:00', '2017-07-16 10:00:00'
];
$(document).ready(function(){
$( "#datepickerListAppointments" ).datepicker({
minDate:'0',
beforeShowDay:
function(dt){
// need to disable days other than tuesday and wednesday too.
return [dt.getDay() === 2 || dt.getDay() === 3, ""];
},
onSelect : function(dateText){
//should disable/enable timepicker times from here!
// parse selected date into moment object
var selDate = moment(dateText, 'MM/DD/YYYY');
// init array of disabled times
var disabledTimes = [];
// for each appoinment returned by the server
for(var i=0; i<fakeDisabledTimes.length; i++){
// parse appoinment datetime into moment object
var m = moment(fakeDisabledTimes[i]);
// check if appointment is in the selected day
if( selDate.isSame(m, 'day') ){
// create a 30 minutes range of disabled time
var entry = [
m.format('h:mm a'),
m.clone().add(30, 'm').format('h:mm a')
];
// add the range to disabled times array
disabledTimes.push(entry);
}
}
// dinamically update disableTimeRanges option
$('input.timepicker').timepicker('option', 'disableTimeRanges', disabledTimes);
}
});
$('input.timepicker').timepicker({
timeFormat: 'h:i a',
interval: 90,
minTime: '9',
maxTime: '10:30am',
defaultTime: '9',
startTime: '9:00',
dynamic: false,
dropdown: true,
scrollbar: false
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-timepicker/1.10.0/jquery.timepicker.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jquery-timepicker/1.10.0/jquery.timepicker.css" rel="stylesheet"/>
<input id="datepickerListAppointments" type="text">
<input class="timepicker" type="text">
source to share