I have been working with some of the code samples for AlpineJS. At first the code would only do the year 2020, and would not move past December 2020.
I have managed to get the code to go past 2020 now, however the dates do not update in the calendar view and I cant see what I am missing.
I have my code on a JSFiddle, can anyone see where I am going wrong, as you can go past December 2020, and select a date which then populates the input field fine.
HTML
<div class="flex items-center justify-center">
<div class="antialiased sans-serif">
<div x-data="app()" x-init="[initDate(), getNoOfDays()]" x-cloak>
<div class="container mx-auto px-4 py-2 md:py-10">
<div class="mb-5 w-64">
<label for="datepicker" class="font-bold mb-1 text-gray-700 block">Select Date</label>
<div class="relative">
<input type="hidden" name="date" x-ref="date">
<input type="text" readonly x-model="datepickerValue" @click="showDatepicker = !showDatepicker" @keydown.escape="showDatepicker = false" class="w-full pl-4 pr-10 py-3 leading-none rounded-lg shadow-sm focus:outline-none focus:shadow-outline text-gray-600 font-medium" placeholder="Select date">
<div class="absolute top-0 right-0 px-3 py-2">
<svg class="h-6 w-6 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
</div>
<!-- <div x-text="no_of_days.length"></div>
<div x-text="32 - new Date(year, month, 32).getDate()"></div>
<div x-text="new Date(year, month).getDay()"></div> -->
<div class="bg-white mt-12 rounded-lg shadow p-4 absolute top-0 left-0" style="width: 17rem" x-show.transition="showDatepicker" @click.away="showDatepicker = false">
<div class="flex justify-between items-center mb-2">
<div>
<span x-text="MONTH_NAMES[month]" class="text-lg font-bold text-gray-800"></span>
<span x-text="year" class="ml-1 text-lg text-gray-600 font-normal"></span>
</div>
<div>
<button type="button" class="transition ease-in-out duration-100 inline-flex cursor-pointer hover:bg-gray-200 p-1 rounded-full" @click="month--; getNoOfDays()">
<svg class="h-6 w-6 text-gray-500 inline-flex" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
</svg>
</button>
<button type="button" class="transition ease-in-out duration-100 inline-flex cursor-pointer hover:bg-gray-200 p-1 rounded-full" @click="month++; getNoOfDays()">
<svg class="h-6 w-6 text-gray-500 inline-flex" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button>
</div>
</div>
<div class="flex flex-wrap mb-3 -mx-1">
<template x-for="(day, index) in DAYS" :key="index">
<div style="width: 14.26%" class="px-1">
<div x-text="day" class="text-gray-800 font-medium text-center text-xs"></div>
</div>
</template>
</div>
<div class="flex flex-wrap -mx-1">
<template x-for="blankday in blankdays">
<div style="width: 14.28%" class="text-center border p-1 border-transparent text-sm"></div>
</template>
<template x-for="(date, dateIndex) in no_of_days" :key="dateIndex">
<div style="width: 14.28%" class="px-1 mb-1">
<div @click="getDateValue(date)" x-text="date" class="cursor-pointer text-center text-sm leading-none rounded-full leading-loose transition ease-in-out duration-100" :class="{'bg-blue-500 text-white': isToday(date) == true, 'text-gray-700 hover:bg-blue-200': isToday(date) == false }"></div>
</div>
</template>
</div>
</div>
</div>
</div>
</div>
</div>
Alpine code
const MONTH_NAMES = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
const DAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
function app() {
return {
showDatepicker: false,
datepickerValue: '',
month: '',
year: '',
no_of_days: [],
blankdays: [],
days: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
initDate() {
let today = new Date();
this.month = today.getMonth();
this.year = today.getFullYear();
this.datepickerValue = new Date(this.year, this.month, today.getDate()).toDateString();
},
isToday(date) {
const today = new Date();
const d = new Date(this.year, this.month, date);
return today.toDateString() === d.toDateString() ? true : false;
},
getDateValue(date) {
let selectedDate = new Date(this.year, this.month, date);
this.datepickerValue = selectedDate.toDateString();
this.$refs.date.value = selectedDate.getFullYear() +"-"+ ('0'+ selectedDate.getMonth()).slice(-2) +"-"+ ('0' + selectedDate.getDate()).slice(-2);
console.log(this.$refs.date.value);
this.showDatepicker = false;
},
getNoOfDays() {
let daysInMonth = new Date(this.year, this.month + 1, 0).getDate();
// find where to start calendar day of week
let dayOfWeek = new Date(this.year, this.month).getDay();
let blankdaysArray = [];
for ( var i=1; i <= dayOfWeek; i++) {
blankdaysArray.push(i);
}
let daysArray = [];
for ( var i=1; i <= daysInMonth; i++) {
daysArray.push(i);
}
this.blankdays = blankdaysArray;
this.no_of_days = daysArray;
}
}
}
https://jsfiddle.net/alr3id/8pLh9cze/
when you reach December, you need to set increase the year rather then the month and set the month variable back to 0. Similar thing when you are decreasing the month and you hit January.
<div>
<button type="button" class="transition ease-in-out duration-100 inline-flex cursor-pointer hover:bg-gray-200 p-1 rounded-full" @click="if(month == 0) {month=11; year--} else {month--}; getNoOfDays()">
<svg class="h-6 w-6 text-gray-500 inline-flex" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
</svg>
</button>
<button type="button" class="transition ease-in-out duration-100 inline-flex cursor-pointer hover:bg-gray-200 p-1 rounded-full" @click="if (month == 11) {month=0; year++} else {month++}; getNoOfDays()">
<svg class="h-6 w-6 text-gray-500 inline-flex" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button>
</div>
Something like https://jsfiddle.net/a0726tjw/3/.
It's still returning the odd error about date being undefined which breaks the order of the days when occurs. There's probably another bug somewhere else but I haven't figured out where yet.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With