Navigating in FullCalendar with previous/next when CustomView has a visibleRange - fullcalendar

My Calendar has a specific view : it shows 31 days (display 4 days before the current day, and 27 days after)
Therefore, I have a dynamic visibleRange for my view
let INIT = moment().subtract(4, 'days').format('YYYY-MM-DD');
let INIT_END = moment(INIT).add(31,'days').format('YYYY-MM-DD');
[...]
type: 'resourceTimeline',
visibleRange: {
start: INIT,
end: moment(INIT).add(31,'days').format('YYYY-MM-DD')
},
buttonText: '31 jours'
}
and previous/next don't seem to work when visibleRange is defined for a custom view.
I tried something involving jQuery and it mostly works, except you have to click first twice on prev/next to change the visibleRange (and you also have to click twice when you go from next to previous or vice-versa).
And I wanted for this :
calendar.setOption('visibleRange', {
start: INIT,
end: INIT_END
})
to work, but in my implementation, it only works once and when it's triggered, clicking on buttons doesn't work anymore.
You can find the code on this CodePen
Can you help me ?

Okay so a colleague of a colleague led me to the solution, thanks a lot to him.
Instead of using visibleRange and trying to manipulate FullCalendar's data with jQuery (very gross), I calculate the difference between my two moments in order to have a duration :
const INIT = moment().subtract(4, 'days');
const INIT_END = moment(INIT).add(31,'days');
let duration = INIT_END.diff(INIT, 'days')
Then I use this duration in the settings of my customView :
resourceTimelineRollingMonth: {
type: 'resourceTimeline',
duration: { days: duration },
buttonText: '31 jours'
}
and for my view to start 4 days before the current day, in the Calendar object, I set :
[...]
defaultDate: INIT.format('YYYY-MM-DD'),
[...]
Which now works flawlessly.

Related

Multi-Month View with different duration and dateIncrement / Prev Button triggers twice

In a custom view for summer and winter semester i tried to set a 7-month view with 6-month steps on clicking the prev/next buttons. (1 month overlapping)
duration: { month: 7 },
dateIncrement: { month: 6 },
Next button works fine, but clicking the prev button triggers event loading twice.
On the first time the calender steps 6-month backwards the event loads again and shows the previous period.
I removed every part of the code, what could produce this behavior, but could't find out.
I tried to reproduce this without a ajax call, again next works fine and prev not:
Codepen
Prev button shows the previous semester on the first click, but stops then.
Any ideas?
Many thanks for your help.
Found a workaround for the bug, works fine:
https://github.com/fullcalendar/fullcalendar/issues/4678
header: {
left: 'backButton,next today',
center: 'title',
},
customButtons: {
backButton: {
click: function () {
calendar.incrementDate({ month: -6 });
}
}
},
bootstrapFontAwesome: {
backButton: 'fa-chevron-left'
},

Protractor e2e test fullcalendar drag & drop

I need to simulate a drag & drop on fullcalendar in the week view with protractor. I found something with coordinates but I'd like a "no browser window dependent solution"... ther's also no way out on finding the exact starting cell in the week view by class or id ...or at least, I couldn't figure how to select a single cell of a row of a day because, using the Chrome's item selector, it seems every row has the same class fc-widget-content and cells are not "selectable" elements.
Are there any other chances?
maybe this is a little bit helpful (also very later ;). I also want to test my app with FullCalendar, but I'm using Cypress (similar to Protractor).
We plan items from an external list and assign it to a resource on a certain day/time in the FullCalendar (we use the scheduler plugin).
I found out that the drag and drop event is somehow intercepted by code, enriching it with for example properties of the event (like date, title and others). How I enriched this data is in the Cypress trigger('drop', data) command. Data is the evenData that is set by the Draggable class:
// Executed on the external list items, where every item we want to plan has class `.fc-event`.
this.draggableContainer = new Draggable(this.containerEl.nativeElement, {
itemSelector: '.fc-event',
eventData(eventEl) {
const id = eventEl.dataset.id;
return {
duration,
id: currentWorkItem.id,
title: currentWorkItem.description,
extendedProps: {
duration,
customRender: true,
data: currentWorkItem,
},
};
}
Then, in your test file (Cypress)
const eventData = {
date: new Date(),
dateStr: new Date().toISOString(),
draggedEl: {
dataset: {
notificationId: '123',
priority: '0',
title: 'Test',
},
},
jsEvent: null,
resource: {
id: '123',
},
event: null,
oldEvent: null,
};
cy.get('.fc-event') // selector for the external event I want to drag in the calendar
.trigger('dragstart')
.get('.fc-time-grid table tr[data-time="07:00:00"] td.fc-widget-content:nth-child(2)') // selector for where I want to drop the event.
.trigger('drop', eventData) // this will fire the eventDrop event
So, .trigger('drop', eventData) will fill the eventDrop info. It is not exactly the same as doing it manually, but works for me.
Caveats:
I haven't found a way to plan it on another resource (we use the resource scheduling plugin of FullCalendar.io). It does not matter that much, because you can specify it in the evenData (resource: { id: 'my-resource-id' } }.
No visual feedback because the drag mirror is not shown. Not a big problem during e2e testing, but it is a bit of a blackbox now. Maybe this is fixable

Convert FullCalendar Event timeFormat to 12 hr for Month view - bug?

I'm using Fullcalendar 2.3.1. I'm trying to convert the time (for example 13:00-14:00) in the month view into 12hr format. Here is my current timeFormat option value:
timeFormat: 'h(:mm)t'
and some example event json:
{
id: "40163152543",
original_id: "3231",
title: "Conference Call",
description: "",
start: "2015-11-20T13:00:00",
end: "2015-11-20T14:00:00",
allDay: false,
color: ""
}
In Week and Day views I am seeing 1p-2p, which is what I want, but in month view I am still seeing 13:00-14:00. Same issue in v 2.6.0! Is this a bug??
It should work. I tried it locally and works fine as per your configuration.
But still you face same issue then try by giving view specific option. May this will solve.
So in the extension library I'm using there was an eventRender callback that I was missing that was overriding the timeFormat option. This is the working override if curious:
eventRender:
function(event, element, view)
{
if(event.end !== null && view.name == 'month')
{
timeformat = event.start.format('h(:mm)t') + ' - ' + event.end.format('h(:mm)t');
element.find('.fc-time').html(timeformat);
}
}
If you have this issue, lookout for an eventRender callback! More documentation on it here: http://fullcalendar.io/docs/event_rendering/eventRender/
Very useful callback, also cool way to do view-specific options, especially with the default view, and #ChintanMirani answer was great too!

FullCalendar skips back to current date rather than staying on current month

I have FullCalendar installed and working great, pulling in courses from my database.
You can view different courses based on clicking a button that submits the page again but passes different criteria.
The Issue is that on reloading of the page and the new content it skips back to the current date which is rather annoying when when you are looking at courses 3 months into the future!!
Does anybody know how to make the calendar go back to the page you where on after you have refreshed the page???
I have a feeling it might be something to do with getdate as I got the following code to work but can't seem to pass the result back through the URL and into the calendar setup.
$('#my-button').click(function() {
var d = $('#calendar').fullCalendar('getDate');
alert("The current date of the calendar is " + d);
});
If you use jquery.cookie you can store the currently viewed date in a cookie for the page being viewed and use that value to set the defaultDate when the page reloads. Pass these in as options when you initialise your calendar:
defaultView: Cookies.get('fullCalendarCurrentView') || 'month',
defaultDate: Cookies.get('fullCalendarCurrentDate') || null,
viewRender: function(view) {
Cookies.set('fullCalendarCurrentView', view.name, {path: ''});
Cookies.set('fullCalendarCurrentDate', view.intervalStart.format(), {path: ''});
}
This code also saves the current view (e.g. month, day etc...)
I used a combination of the two above. I set the localStorage value for the start date when creating, moving, or resizing an event as well as viewRender and then assigned that value to the defaultDate.
defaultDate: localStorage.getItem('Default_FullCalendar_Date'),
viewRender: function(view) {
localStorage.setItem('Default_FullCalendar_View', view.name);
...
},
select: function(start, due){
localStorage.setItem('Default_FullCalendar_View', start);
...
},
eventDrop: function(event, delta, revertFunc, jsEvent, ui, view){
localStorage.setItem('Default_FullCalendar_View', event._start._d);
...
},
eventResize: function(event, delta, revertFunc, jsEvent, ui, view){
localStorage.setItem('Default_FullCalendar_View', event._start._d);
...
}
Works like a charm.
You can use gotoDate method:
var d = $('#calendar').fullCalendar('getDate');
$('#calencar').fullCalendar( 'gotoDate', d.getFullYear(), d.getMonth(), d.getDate() )
Here is an updated answer for version 4 and 5 of fullcalendar.
since viewRender is no longer an option in these versions. I came up with a different approach using the loading option.
The loading option will give you a boolean argument stating whether the calendar is done loading or not. Inside that function I check if the calendar is done loading and if so, I set the calendar date to localStorage. Next I created an if else statement before the fullcalendar object to check if the localstorage item exists, and if so I set the defaultDate option in the calendar object to to localStorage date; if not, I just set it to today's date.
Example:
let viewDate;
const savedDate = localStorage.getItem("calDate");
if (savedDate !== null) {
viewDate = new Date(savedDate);
} else {
viewDate = today();
}
const calendarElement = document.getElementById('your_calendar');
const calendar = new FullCalendar.Calendar(calendarElement, {
defaultDate: viewDate,
loading: function(stillLoading) {
if (stillLoading === false) {
// When Calendar is done loading....
localStorage.setItem("calDate", calendar.getDate());
}
},
});

How to cancel old selection in fullCalendar?

I use jQuery fullCalendar (http://arshaw.com/fullcalendar/docs/selection/unselectAuto/)
I use Selectable version of this calendar (http://arshaw.com/js/fullcalendar/demos/selectable.html)
It's working fine however I want to cancel/delete my old selections if I continue selecting new dates.
Lets say I chose 1 Jan and gave a title to it.
When I try to select 2 Jan, I want to see only 2 Jan selection.
I thought unselectAuto is for this but I couldnt manage to make it work :(
Any ideas?
I used unselectAuto right under
selectable: true,
unselectAuto: true,
First it's still necessary to use the $('#yourCalendar').fullCalendar('unselect'); function.
The second thing that I needed to do, was to specify how the unselect callback was going to behave (when setting up the fullcalendar options). For me I had to unbind the submit button from my form
unselect: function(){
$('#submitButton').unbind();
},
It worked great!
I was able to reach this conclusion after reading this post "multiple events created"
u can try this way, this works for me :)
var liveDate = new Date(); // current Date
var calendar = $('#calendar').fullCalendar({
select: function (startDate, endDate) {
if (liveDate > startDate) {
alert('Selected date has been passed');
return false;
} else {
//do your wish
}
calendar.fullCalendar('unselect');
}
});
Had the same problem but my user was interfacing directly with the calendar and multiple events were being generated. ie. not through a form with a button and therefore nothing to "unbind" as many of the previous solutions.
To only allow one selection and to clear previous submissions I changed the select function as follows:
select: function(start, end) {
var title = "Desired Booking";
var eventData;
eventData = {
title: title,
start: start,
end: end
};
$('#calendar').fullCalendar('renderEvent', eventData, true); },
select: function(start, end) {
$('#calendar').fullCalendar('removeEvents');
$('#calendar').fullCalendar('rerenderEvents')
var title = "Desired Booking";
var eventData;
eventData = {
title: title,
start: start,
end: end
};
$('#calendar').fullCalendar('renderEvent', eventData, true); },
This did the trick for me.
I had problems with unselectAuto also. Sometimes it would unselect when I didn't want it to, and sometimes it would NOT unselect when I DID want it to. My solution was to manually trigger the unselect method.
Here's how to unselect all currently selected:
$('#yourCalendar').fullCalendar('unselect');
You can put this line of code inside custom jQuery events that you bind outside of the plugin. You can also include it in fullCalendar callbacks, etc...
Hope this helps.
Scott
Here is an exemple of Version 5 doing the unselect
You could do it by :
const calendarApi = selectInfo.view.calendar;
calendarApi.unselect(); // clear date selection
Use this code
$('#trainings_modal').on('hidden', function () {
$('#trainings_modal *').unbind(); // Unbind all events
});
Unbind on hide form with any method (i.e esc press, or out key)

Resources