FullCalendar VueJS - Update date range - vue.js

I use the official FullCalendar VueJS component, and I would like to update the current range displayed in the view (DayGridMonth here) : 1 month, 2 months, 3 months, custom period
According to the "documentation", the visibleRange property can be updated thanks to the function setOption() (https://fullcalendar.io/docs/visibleRange), but it doesn't work for me : the property is well updated in component, but the view wasn't updated.
I also tried to update state manually, without result.
This is my draft function to do this
updateCurrentDate: function () {
const calendarApi = this.$refs.fullCalendar.getApi();
const date = new Date(calendarApi.getDate());
let endRange;
this.currentPeriodRange = calendarApi.state.dateProfile.activeRange;
this.currentPeriodLabel = moment(date).format('MMMM YYYY');
if (this.currentView === 'month') {
endRange = moment(this.currentPeriodRange.start).add(2, 'month');
this.currentPeriodRange.end = endRange.toDate();
// Not working
calendarApi.setOption('visibleRange', this.currentPeriodRange);
// No one of these test work
calendarApi.state.dateProfile.activeRange = this.currentPeriodRange; //
calendarApi.state.dateProfile.currentRange = this.currentPeriodRange;
calendarApi.state.dateProfile.renderRange = this.currentPeriodRange;
}
if (this.currentPeriodRange.start !== this.currentPeriodRange.end) {
this.currentPeriodLabel = this.currentPeriodLabel + ' - ' + endRange.format('MMMM YYYY');
}
return;
},
Thanks for reading and answering

Related

JS - How to implement the YTD (Year To Date) logic in order to do Date selection

I am trying to implement a method for a Date selection in vue-chartjs. Here is the function that i have used in the methods life cycle hook:
DateSelect(event) {
const period = event.target.value
let minValue = new Date(Math.max(...this.date) * 1000)
const axisXMin = new Date(Math.min(...this.date) * 1000)
switch (period) {
case '1m':
minValue.setMonth(minValue.getMonth() - 1)
break
case '3m':
minValue.setMonth(minValue.getMonth() - 3)
break
case 'ytd':
minValue.setFullYear(minValue.getFullYear() - minValue.getMonth()) //Here I want to implement the YTD Logic.
break
default:
minValue = axisXMin
}
const data = this.data.filter(el => {
return el.x >= minValue
})
this.GraphOutput(data) // this is vue-chartjs function.
}
Here the logic '1m' and '3m' works absolutely fine, as they display the previous 1month's and 3month's chart to the user when the respective button is clicked.
I want to know how to implement the YTD (Year to Date) Logic in the function that i have used above. Please do help me.
As far I understand you may need a full year of data in the graph. So that you need to set the minimum value as below:
case 'ytd':
minValue.setYear(minValue.getFullYear() - 1);
break

FullCalendar V4 - How to account for shorter months in a recurring event series?

I'm using FullCalendar v4-alpha-3 with the RRule plugin to generate recurring events. It works as expected with only one problem: how do I modify a recurring event to account for months with fewer days than the starting month in a series?
For example, if the first monthly occurrence happens on January 29, 2019; the event will be repeated on the 29th of all subsequent months except in February since it only has 28 days (leap years excluded).
I've tried resetting dtstart to the first day of the following month. It works, except the event is no longer recursive.
Here's a stripped down snippet of my setup:
let calendar = new Calendar(calendarEl, {
plugins: [ rrulePlugin ],
events: [
{
rrule: 'DTSTART:20190129 RRULE:FREQ=MONTHLY;UNTIL=20200130;COUNT=13;BYMONTHDAY=29'
}
],
eventRender: function(info) {
...
// reset start date to the first day of the following month
// if current month has fewer days than base month
let start = event.start;
let day = start.getDate();
let now = new Date();
let currentMonth = now.getMonth();
let currentYear = now.getFullYear();
let daysInCurrent = getDaysInMonth(currentMonth + 1, currentYear);
let nextStart = start;
if (day > daysInCurrent) {
nextStart = new Date(currentYear, currentMonth + 1, 1);
event.setStart(nextStart);
event.setEnd(null);
}
}
});
I'd appreciate any insight.
Not quite the solution I hoped for, but RRule's bysetpos property seems to offer the next best alternative as it allows for a fallback date in case the one specified doesn't exist.
For example, the following would generate an occurrence on the 30th of every month; or the last day of the month if the 30th doesn’t exist:
FREQ=MONTHLY;BYMONTHDAY=28,29,30;BYSETPOS=-1.
Sourced from: https://icalevents.com/2555-paydays-last-working-days-and-why-bysetpos-is-useful/
I know this is an old question but maybe this will be usefull for someone:
I'm using momentjs library
monthly:
let endofmonth = moment('2020-02-29', "YYYY-MM-DD").endOf('month').format('DD');
let curday = moment('2020-02-29, "YYYY-MM-DD").format('DD');
single_event.title = title;
single_event.rrule = {};
single_event.rrule.freq = 'monthly';
single_event.rrule.dtstart = start_date;
single_event.rrule.interval = reminder_interval;
single_event.rrule.count = reminder_count;
if(endofmonth == curday){
// Checking if given day of the month is last
single_event.rrule.byweekday = ['mo','tu','we','th','fr','sa','su'];
single_event.rrule.bysetpos = -1;
}
else{
single_event.rrule.bymonthday = parseInt(curday);
}
calendar_events.push(single_event);
var calendar = new FullCalendar.Calendar(calendarEl, {
...
events: calendar_events
});
yearly:
single_event.title = title;
single_event.rrule = {};
single_event.rrule.dtstart = start_date;
single_event.rrule.count = parseInt(reminder_count);
if(endofmonth == curday){
// Checking if given day of the month is last
single_event.rrule.freq = 'monthly'; // Will work as yearly if interval is 12
single_event.rrule.interval = parseInt(reminder_interval)*12;
single_event.rrule.bymonthday = [28,29,30,31];
single_event.rrule.bysetpos = -1;
}
else{
single_event.rrule.freq = 'yearly';
single_event.rrule.bymonthday = parseInt(curday);
}
calendar_events.push(single_event);
var calendar = new FullCalendar.Calendar(calendarEl, {
...
events: calendar_events
});

vue.js dynamically adding to a list of components

I'm having trouble dynamically adding to a list of components.
I've defined the list in the data element "things" of the vue document. For each object in "things" there is a component loaded onto the page
data() {
return {
things: []
}
}
I use something like the code below to load each of the things on the page.
<div v-for="thing in things" :key="thing.objectId">
Then I load in more elements and add them to the list
let temp = JSON.parse(JSON.stringify(results))
vm.things = vm.things.concat(temp)
And when I run it in dev I get the following
[Vue warn]: You may have an infinite update loop in a component render
function.
Other then the error message, the code works in dev mode but crashes the browser when run in production.
I've narrowed it down to this code, there is a bit in the loop which prints out a heading which is the month the data belongs to, so it might say January, then list all the data under january, then onto the next month and so on
showDate(data) {
this.currentDataMonth = helperfunctionsgetDate_format_month_year(data)
if (this.currentDataMonth != this.currentmonth) {
this.currentmonth = this.currentDataMonth
return "<h2>" + this.currentmonth + "</h2>"
} else {
return ""
}
Your issue is caused by the fact that you both modify the state, and use the state from the same method.
showDate(data) {
this.currentDataMonth = helperfunctionsgetDate_format_month_year(data) // set of the state
if (this.currentDataMonth != this.currentmonth) { // get of the state
this.currentmonth = this.currentDataMonth
return "<h2>" + this.currentmonth + "</h2>"
} else {
return ""
}
Since you directly use those variables inside your function, make them local to the function
showDate(data) {
const currentDataMonth = helperfunctionsgetDate_format_month_year(data)
if (currentDataMonth != undefined) {
const currentmonth = currentDataMonth
return "<h2>" + currentmonth + "</h2>"
} else {
return ""
}
Since the purpose of the code is to list every month under its own heading, you should do that using a computed function to return a list of data per month, and use 2 loops to loop over that

How to prevent user to enter specific times in datetimepicker?

I am using angular-bootstrap-datetimepicker. I know how to restrict the user from entering specific dates.
$dates.filter(function(date){
return (date.localDateValue() <= new Date().valueOf()-(24*60*60*1000));
}).forEach(function(date){
date.selectable = false;
})
This code insode startDateBefore render, prevents user from entering dates 24h past the current date.
But now I want users to enter spectic times only. Like user can select only times between 10:05am to 11:10pm. I am unable to do that. Documentation doesn't specify on how to add filter to hour and minutes. Any help on that.
In Angular Date Time Picker, the beforeRender function also takes parameter called view. So we can use the view==='hour' to restrict users from entering past hours. I was missing the code for hours.
function startDateBeforeRender ($view, $dates, $leftDate, $upDate, $rightDate) {
var today = moment().valueOf();
$dates.filter(function (date) {
return date.localDateValue() < today -(24*60*60*1000)
}).forEach(function (date) {
date.selectable = false;
});
// to restrict hours by admin
if ($view === "hour") {
// restict previous hours
$dates.filter(function (date) {
return date.localDateValue() < today
}).forEach(function (date) {
date.selectable = false;
})
}
}
date = new Date().valueOf();
if( date > 1000*(10*60+5) ){
if( date < 1000*(23*60+10) ){
//Code green, I repeat, CODE GREEN!
}
}

Multiple API calls simultaneously in marionetteJS

I use forcast api to get weather data. In marionette I use model to define API rulRoot as
var weatherApi = Backbone.Model.extend({
defaults:{
lat:"",
lng:"",
timeStamp:"",
units:"",
response:""
},
urlRoot: function(){
return '/api/web/forecast?lat='+ this.get("lat") + '&long=' + this.get("lng") +'&time=' + this.get("timeStamp") + '&units='+this.get("units");
}
});
Then I instantiate as
weatherApiGddObj = new weatherApiInstance();
I used this object to fetch api call response. Now want I want is to make multiple api call simultaneously like from today to next 30 days, So If I do one after another then It'll take lot of time to get all response. How do I do this with marionette?
It would be good to have a method that allows you to grab data for the range of days in one request. But according to your conditions I'd do it like this:
var date, startDate = someTimestamp, day = 86400,
endDate = startDate + day * 30, promises=[];
for(date = startDate; date < endDate; date += day){
weatherApiGddObj.set('timestamp', date);
promises.push(weatherApiGddObj.fetch());
}
$.when.apply($,promises).done(function(){
var data = Array.slice.call(arguments);
console.log(data);
});
I suggest you to read about Deferred Object