0
votes

I'm trying to add events to all days of the calendar on page load and they need to have one of three colors (red, yellow, green) based on some data connected to each day. Simple example with events for three days:

example of fullcalendar with color coded events

I have a model that contains data on how many free pallets there are for orders on a given date. If there's less than 10 free pallets, the event should be red, if its between 10 and 149 it must be yellow and so on (as seen on the example).

This is the current "FullCalendar" script:

<script type="text/javascript">
    var calendar = new FullCalendar.Calendar($("#calendar")[0], {
        plugins: ['interaction', 'dayGrid'],
        height: 'auto',
        defaultView: 'dayGridMonth',
        weekNumberCalculation: 'ISO',
        weekNumbers: true,
        events: [
            {
            title: '150-300',
                start: '2020-07-16',
            color: 'green'
            },
            {
            title: '10-149',
                start: '2020-07-15',
            color: 'yellow'
            },
            {
            title: '<10',
                start: '2020-07-14',
            color: 'red'
            }],
        dateClick: function (info) {
            window.location.href = "Incoming?date=" + info.dateStr;
        }
    });
    calendar.render();
    calendar.select('@(Model.Date?.ToString("yyyy-MM-dd"))');
</script>

The hardcoded events are just for the example.

I want to, when the page loads, fill the calendar with a colored event on each date in the month, according to the data on amount of free pallets. How can I dynamically create these events from data given by a model in my MVC (.Net) application?

I have tried several suggested solutions from this forum on dynamically adding events, but they either do not work or are associated with post actions, which I don't believe is necessary in this case.

UPDATE

I have tried to create a JsonResult action in my controller, which seems to create a valid Json string, that I can feed my FullCalendar. It does however not seem to work. I have this action:

public JsonResult GetCalendarEvents(string id, DateTime? date)
        {
         //Database related code to get dates and their amount of free pallets (this is where I use the id and date parameters)
                var idEvent = 1;
                foreach (var v in days)
                {
                    var title = "";
                    var color = "";
                    var freecap = (v.DayOfWeek == DayOfWeek.Friday ? 200 : 300) - model.Incomings.Where(x => x.ExpectedDate == v &&
                            x.ExpectedPallets.HasValue).Sum(x => x.ExpectedPallets);


                    if(freecap >= 150)
                    {
                        title = "150-300";
                        color = "green";
                    } else if(freecap < 150 && freecap >= 10)
                    {
                        title = "10-149";
                        color = "yellow";
                    } else
                    {
                        title = "<10";
                        color = "red";
                    }

                    events.Add(new CalendarEvent { id = idEvent, title = title, allDay = "", start = v.Date.ToString().Substring(0,10), end = v.Date.ToString().Substring(0, 10), color = color });
                    
                    idEvent++;
                }
            }

            return Json(events, JsonRequestBehavior.AllowGet);

The Json result looks like this:

[{"id":1,"title":"150-300","allDay":"","start":"19-07-2019","end":"19-07-2019","color":"green"},{"id":2,"title":"150-300","allDay":"","start":"22-08-2019","end":"22-08-2019","color":"green"},{"id":3,"title":"150-300","allDay":"","start":"30-08-2019","end":"30-08-2019","color":"green"}]

The attributes id, allDay and end was added because of the top answer on this post: Jquery Full Calendar json event source syntax but that did not help.

None of the events shows up in the calendar, but the page and calendar loads just fine (without events). What am I missing here?

1
fullcalendar.io/docs/events-json-feed - does that help? Have a separate JSON feed for your events, rather than putting them in the model in your view. That way you get a non-static list which can update as the user moves through date ranges. And of course you can use code to generate the event data, including calculating the colour, and then serialise it to JSONADyson
Huh? I'm really not sure what you are trying to say. The number of events has no impact on the URL. You simply nominate a single URL as the source of events and tell fullCalendar that URL. Fullcalendar will send a request to that URL (it will also append the start and end dates of the current view to the URL, to help the server know which events to return). Then your server, when it receives that request, must send back a list of events, in the correct JSON format, as the response to that request. That list goes in the response, it has nothing to do with any URLs.ADyson
Yes, absolutely. in MVC it can be done by making the action return a JsonResultADyson
Your start and end dates need to be be in YYYY-MM-DD format. (DD-MM-YYYY is ambiguous, it can be mistaken for MM-DD-YYYY e.g. 03/07/2019 - is it 3rd July or 7th March?? fullCalendar cannot tell which format you intended it to represent, therefore it doesn't accept it, so you must use YYYY-MM-DD which is a non-ambiguous format.)ADyson
P.S. This is mentioned in the documentation here and in more detail hereADyson

1 Answers

0
votes

With the help of user @ADyson I have worked out a solution to my problem(s). Here is a somewhat complete example and answer if anyone else happens to stumble across the same issues or want to work with the FullCalender events by feeding it JSON in an MVC context.

First I have an event class with the necessary attributes (I actually only use the title, start and color attributes, but the rest might be required as well, which is why I added them, as per this post Jquery Full Calendar json event source syntax):

public class CalendarEvent
    {
        public int id { get; set; }
        public string title { get; set; }
        public string allDay { get; set; }
        public string start { get; set; }
        public string end { get; set; }
        public string color { get; set; }
    }

Then I have in my controller the action GetCalendarEvents like this:

public JsonResult GetCalendarEvents(string id, DateTime? date)
        {
         //Database related code to get dates and their amount of free pallets (this is where I use the id and date parameters)
                var idEvent = 1;
                foreach (var v in days)
                {
                    var title = "";
                    var color = "";
                    var freecap = (v.DayOfWeek == DayOfWeek.Friday ? 200 : 300) - model.Incomings.Where(x => x.ExpectedDate == v &&
                            x.ExpectedPallets.HasValue).Sum(x => x.ExpectedPallets);


                    if(freecap >= 150)
                    {
                        title = "150-300";
                        color = "green";
                    } else if(freecap < 150 && freecap >= 10)
                    {
                        title = "10-149";
                        color = "yellow";
                    } else
                    {
                        title = "<10";
                        color = "red";
                    }

                    events.Add(new CalendarEvent { id = idEvent, title = title, allDay = "", start = v.Date.ToString().Substring(0,10), end = v.Date.ToString().Substring(0, 10), color = color });
                    
                    idEvent++;
                }
            }

            return Json(events, JsonRequestBehavior.AllowGet);
}

The logic in the action is mostly just getting the right data from our database and determining which color and name the event should have (This is determined by the amount of free pallets on our warehouse on a given date). This method could do whatever you need it to, the essence of it is that it creates a list of events and returns them as a Json result.

In my View, where the FullCalendar script and widget is located I refer the events to the action like this (remember to change the route, controller, action and id string to fit your own):

events: '@Url.HttpRouteUrl("Default", new { controller = "Home", action = "GetCalendarEvents", id = "DOD" })'

There might appear a string "12a" in front of your title on all the events. This is because it indicates the start time of the event (which I have not set). In either case, you can add these two lines to the script if you want to get rid of it:

timeFormat: 'H(:mm)', // uppercase H for 24-hour clock
displayEventTime: false

My full FullCalendar script looks like this:

<script type="text/javascript">
    var calendar = new FullCalendar.Calendar($("#calendar")[0], {
        plugins: ['interaction', 'dayGrid'],
        height: 'auto',
        defaultView: 'dayGridMonth',
        weekNumberCalculation: 'ISO',
        weekNumbers: true,
        events: '@Url.HttpRouteUrl("Default", new { controller = "Home", action = "GetCalendarEvents", id = "DOD" })',
        timeFormat: 'H(:mm)', // uppercase H for 24-hour clock
        displayEventTime: false,
        dateClick: function (info) {
                window.location.href = "Incoming?date=" + info.dateStr;
            }
        });
    calendar.render();
    calendar.select('@(Model.Date?.ToString("yyyy-MM-dd"))');
</script>

The returned JSON result should look something like this:

[{"id":1,"title":"150-300","allDay":"","start":"2019-07-19","end":"2019-07-19","color":"green"},{"id":2,"title":"150-300","allDay":"","start":"2019-08-22","end":"2019-08-22","color":"green"},{"id":3,"title":"150-300","allDay":"","start":"2019-08-30","end":"2019-08-30","color":"green"}]

It is important to note here, as @ADyson pointed out, that the date format needs to be yyyy-MM-dd (which is why my updated post did not work). If you need more information, check the FullCalendar documentation, which @ADyson also linked: Event Parsing and Events (as a json feed)