I want to disable date via loading by ajax. When datepicker onpens and month changed it must setDisabledDates from loaded array
I tryed set it by show and changeMonth event, but i did't find any example how to make it.
Please help me to solve this problem
v1.7.0-dev
var array = new Array();
function load_reservation(stock, year = null, month = null, callback){
jQuery.ajax({
method: "POST",
url: "'.Url::to(['site/ajax-load-reservation']).'",
data: { "stock": stock, "year": year, "month": month },
success: function(data) {
if(data.result==1){
callback(data.array);
}
else callback(null);
},
dataType: "json",
async: false
});
}
$(".book").each(function(){
var id = $(this).attr("data-stock_id");
load_reservation(id, null, null, function(result){
array[id] = result;
console.log("Loaded dates for #"+ id +": "+array[id]);
});
});
$(".book").datepicker({
multidate: true,
startDate: "1d",
language: "ru",
format: "yyyy-mm-dd",
}).on("click", function(e){
var id = $(this).attr("data-stock_id");
e.datesDisabled = array[id];
}).on("changeMonth", function(e) {
var id = $(this).attr("data-stock_id");
var year = e.date.getFullYear();
var month = e.date.getMonth() + 1;
load_reservation(id, year, month, function(result){
array[id] = result;
console.log("Onchange Loaded dates for #"+ id +": "+array[id]);
});
setDatesDisabled = array[id];
console.log(e);
return e;
});
Jsfiddle example to reproduce the problem.
Questions like this one should go to stackoverflow. But to push you in the right direction. There seems to be an async issue. setDatesDisabled = array[id]; runs before your callback. Also you are not calling setDatesDisabled method but just setting a global setDatesDisabled var.
I think this one can be closed.
I'm not sure there is any implementation we could do in our side for ajax loading.
There's a snippet that should works well in your case:
<style>
body div.datepicker td.disabled {
background: #ab4646;
color: #e47c7e;
border-radius: 0;
}
body div.datepicker[data-state="loading"] div.datepicker-days::before {
content:'';
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(158, 158, 158, 0.35);
}
body div.datepicker[data-state="loading"] div.datepicker-days::after {
content:'';
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: no-repeat center center url(http://www.e-tlf.com/wp-content/plugins/nice-login-register-widget/images/loading_transparent.gif);
}
</style>
<input class="booking-picker">
<script>
$(document).ready(function () {
// We isolate varaible for each picker
$('.booking-picker').each(function () {
var input, picker, xhr, token,
selected_date, last_selected_date, dates,
timetowait;
xhr = null;
token = null;
input = $(this);
timetowait = 300;
selected_date = new Date();
last_selected_date = null;
// Load the dates
function loadDates(c_token) {
// If the token don't match we don't make the call
// This allow to avoid call spaming
if (c_token !== token) {
return;
}
picker.attr('data-state', 'loading');
// Replace by $.ajax
fakeAjaxCall({
url: '/booking',
data: {
date: selected_date
}
}, function (data) {
last_selected_date = selected_date;
picker.attr('data-state', 'loaded');
dates = data;
input.datepicker('setDatesDisabled', data);
});
}
// When we change month we change the stored date
input.on('changeMonth', function (event) {
selected_date = event.date;
});
// When show is trigerred we load the dates
input.on('show', function (event) {
// Only get the picker once
if (picker === undefined) {
picker = $(this).data().datepicker.picker;
picker.attr('data-state', '');
}
// If we actually didn't change month we don't go further
if (last_selected_date === selected_date) {
return;
}
// Abort any request ongoing
if (xhr !== null && typeof xhr.abort === 'function') {
xhr.abort();
}
var new_token = new Date();
token = new_token;
setTimeout(function () {
loadDates(new_token);
}, timetowait);
});
input.datepicker({
format: 'yyyy-mm-dd',
updateViewDate: false,
beforeShowDay: function (date) {
// Always disable days out of the month if you only want to load shown month
// Else you'll have to load past and next month as well as current month
return date.getMonth() === selected_date.getMonth();
}
});
});
});
// Fake ajax call that will generate 4 to 15 disabled dates
window.fakeAjaxCall = function (options, callback) {
setTimeout(function () {
var i, j, y, m, d, dates = [];
y = options.data.date.getUTCFullYear();
m = options.data.date.getMonth() + 1;
j = Math.random() * (15 - 4) + 4;
for (i = 0; i < j; i += 1) {
d = Math.floor(Math.random() * (new Date(y, m + 1, 0).getDate() - 1) + 1);
dates.push([y, m, d].join('-'));
}
callback(dates);
}, (Math.random() * (20 - 3) + 3) * 100);
}
</script>
Thank you for the example! I'm trying to achieve same behavior and having strange side effect of date jumping back to "today" after month is changed. Here I have converted your example into jsfiddle http://jsfiddle.net/Algis78/5x9e9ex4/ to demonstrate what I mean. Where did I go wrong?
@asarapas What you are facing is a known and confirmed bug in bootstrap-datepicker: #2054 You could avoid the bug if you set updateViewDate option to false or write a work-a-round that updates viewDate by using private api (#1978) after you called setDatesDisabled.
Of course you could also write an PR that fixes the bug in bootstrap-datepicker. :-)
After looking at the source code realized that updateViewDate option is available in v1.7.0-RCx. Updated Fiddle to reference latest RC version and everything works as expected. Thank you.