Click here to Skip to main content
12,403,811 members (68,792 online)
Click here to Skip to main content
Add your own
alternative version

Stats

248.9K views
27.3K downloads
171 bookmarked
Posted

Full calendar – A complete web diary system for jQuery and C# MVC

, 20 Aug 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
Using FullCalendar, jQuery, and MVC to give your web-app ready-to-go appointment diary functionality.

Introduction

This article describes using the very fine open source JQuery plugin “FullCalendar” by Adam Shaw to develop an appointment booking system. I will demonstrate numerous ways to use the plugin and show how it can integrate with an SQL Backend with Entity-Framework. The aim of this article is give you almost everything you need, that you can tweak immediately, to bring diary/appointment functionality to your MVC application. This is a complete walk-through including setup of a linked EF database in SQL. I am going to use the Twitter Bootstrap framework to help speed things along. I am also going into a lot of detail to help those wishing to use the plugin to get started as fast as possible. The attached project is written in C# MVC 4. 

Background

I was recently looking for a good reliable web based diary plugin that would allow me to give solid appointment management functionality. Apart from some commercial offerings the most suitable solution open source plugin I found was FullCalendar. Get it here. The demo scenario will have the following functionality:

  • For each day, manage appointments
  • In month view see overview summary information on all appointment events

Gotchas

Some of the gotchas included date format (this plugin uses a Unix timestamp), and having to work with multiple plugin data sources as I wanted different kinds of data queried depending on the view of the calendar being seen (day, week, month..). I also had some issues with trying to get the events rendering exactly how I wanted - the DOH! moment came when I realised I was referencing some CSS in the wrong order/sequence. For drag/drop functionality the plugin depends on jQueryUI to be included, and finally, in order to stop the plugin triggering before I wanted it to, I had to control the flow of loading of data carefully. 

Setting things up

To get started:

  1. Create a new C# MVC project and clear out the default view templates.
  2. Download FullCalendar from here.
  3. Download Twitter Bootstrap (I am using the stable version 2.3.2 until v3 is out of RC).
  4. For both libraries, unpack and place the CSS file in your /Content folder, and the JS scripts in the /Scripts folder.
  5. In your MVC project, add the bootstrap files to your script bundles. This is in BundleConfig.cs and is located in your App_Start folder.
  6. You will also note I have added the JQuery-UI JS file to my bundle - this is needed to support drag/drop.

  7. We will do our work in the default index.cshml page, so in there, place a DIV to hold the plugin:
  8. <div id='calendar' style="width:65%"></div>

    (note that the inline style is simply to force the width for screenshots inside the CodeProject publishing size guidelines!)

  9. Finally, to prove its at least loading and rendering correctly we will add some basic JS when the document is ready and loaded:

    The initialization settings tell the plugin what to show in the header, the default view (in this case "agenda day" ..familiar to most), and to have a default time slot of 15 minutes.

When we run the project, as expected, the plugin appears:

OK, so let's get busy!

Using the code

Rather than use dummy client-side data, I wanted to show how we might store and manipulate data in a working environment, so I put together an SQL database to store data and linked to it using Entity Framework. (The SQL source is attached to this article).

The SQL table is called "AppointmentDiary" and contains these fields:

The ID is an auto-increment, Title get displayed within the Calendar control as an event, SomeImportantKey represents a referential link to some other data table, DateTimescheduled is the diary date/time, Appointment length is an integer that represents the number of minutes the appointment lasts, and finally StatusENUM is an integer that links to an ENUM value to say if the appointment is an enquiry, a booking, confirmed etc.

We add a new Entity Data Model to the project and point it at our new database and table. This creates an EDMX file that in our case we call "Diary" and reference as "DiaryContainer".

As this example is date based, I didn't want to pre-populate it with data, because any events I stored would be out of date the day after publishing! For this reason I put together a quick method that initialises the database. The method is called by pressing a button in the browser that sends an Ajax call to the application (lets minimise full server round-trips when we can!).

The button starts life as a link:

<a href="#" id="btnInit" class="btn btn-secondary">Initialise database!</a>

but through the wonder of Bootstrap, the addition of the class "btn" turns the link into a button, and "btn-secondary" gives it a gray colour.

The script to call the initialise code is basic enough:

$('#btnInit').click(function () {
  $.ajax({
        type: 'POST',
        url: "/Home/Init",
        success: function (response) {
            if (response == 'True') {
                $('#calendar').fullCalendar('refetchEvents');
                alert('Database populated! ');
            }
            else {
                alert('Error, could not populate database!');
            }
        }
    }); 
});  

Server-side, we have a controller "/Home/Init" that calls a method in a shared file called Utils called "InitialiseDiary". The objective of this method is to generate a series of test diary appointments that centre around the current date. It creates some items for the current date, and others before and after the date.

public static bool InitialiseDiary() { 
    // init connection to database
    DiaryContainer ent = new DiaryContainer();
    try
    { 
        for(int i= 0; i<30; i++){
        AppointmentDiary item = new AppointmentDiary();
        // record ID is auto generated
        item.Title = "Appt: " + i.ToString();
        item.SomeImportantKey = i;
        item.StatusENUM = GetRandomValue(0,3); // random is exclusive - we have three status enums
        if (i <= 5) // create ten appointments for todays date
        {
            item.DateTimeScheduled = GetRandomAppointmentTime(false, true);
        }
        else {  // rest of appointments on previous and future dates
            if (i % 2 == 0)
                item.DateTimeScheduled = GetRandomAppointmentTime(true, false);
                // flip/flop between date ahead of today and behind today
            else item.DateTimeScheduled = GetRandomAppointmentTime(false, false);
        }
        item.AppointmentLength = GetRandomValue(1,5) * 15;
        // appoiment length always less than an hour in this demo in blocks of fifteen minutes

        ent.AppointmentDiary.Add(item);
        ent.SaveChanges();
    }
    }
    catch (Exception)
    {
        return false;
    }

    return ent.AppointmentDiary.Count() > 0;         
}

This method calls two other supporting methods, one which generates a random number, the other that generates a random date/time.

/// <summary>
/// sends back a date/time +/- 15 days from todays date
/// </summary>
public static DateTime GetRandomAppointmentTime(bool GoBackwards, bool Today) {
    Random rnd = new Random(Environment.TickCount); // set a new random seed each call
    var baseDate = DateTime.Today;
    if (Today)
        return new DateTime(baseDate.Year, baseDate.Month, 
                baseDate.Day, rnd.Next(9, 18), rnd.Next(1, 6)*5, 0);
    else
    {
        int rndDays = rnd.Next(1, 15);
        if (GoBackwards)
            rndDays = rndDays * -1; // make into negative number
        return new DateTime(baseDate.Year, baseDate.Month, 
          baseDate.Day, rnd.Next(9, 18), rnd.Next(1, 6)*5, 0).AddDays(rndDays);             
    }
} 

Now we have that, we can generate sample data by running the application and clicking the button (made delicious and wonderful by the magic of the twittering bootstrap....) however, before we click that object of wonder, lets put in a controller and method to send our sample data back to the plugin....

Full calendar can create diary "events" to render in a number of different ways. One of the more common is to send in data as a JSON list. 

"Events" need at a minimum the following information:

  • ID: a unique identifier for the diary item
  • Title: Some text to render on the screen
  • Start: Starting date/time of the event
  • End: Ending date/time of the event

You can also send some other information back such as the color you would like the event to be on the screen, a CSS class-name if you wish to render the event in a particular way. You can also send back any other information you might need to handle client-side, for example, key fields to related data tables etc.

To hook into the data table, I created a model called DiaryEvent, and gave it some fields that map to the Entity model.

public class DiaryEvent
{
   public int ID;
   public string Title;
   public int SomeImportantKeyID; 
   public string StartDateString;
   public string EndDateString;
   public string StatusString;
   public string StatusColor;
   public string ClassName;
   ...
}

In addition I added some methods to extract information and save it back. The first we are interested in takes as parameters, a start and end date, and returns a list of DiaryEvents:

public static List<DiaryEvent> LoadAllAppointmentsInDateRange(double start, double end)
{
    var fromDate = ConvertFromUnixTimestamp(start);
    var toDate = ConvertFromUnixTimestamp(end);
    using (DiaryContainer ent = new DiaryContainer())
    {
        var rslt = ent.AppointmentDiary.Where(s => s.DateTimeScheduled >= 
            fromDate && System.Data.Objects.EntityFunctions.AddMinutes(
            s.DateTimeScheduled, s.AppointmentLength) <= toDate);
        List<DiaryEvent> result = new List<DiaryEvent>();
        foreach (var item in rslt)
        {
            DiaryEvent rec = new DiaryEvent();
            rec.ID = item.ID;
            rec.SomeImportantKeyID = item.SomeImportantKey;
            rec.StartDateString = item.DateTimeScheduled.ToString("s");
            // "s" is a preset format that outputs as: "2009-02-27T12:12:22"

            rec.EndDateString = item.DateTimeScheduled.AddMinutes(item.AppointmentLength).ToString("s");
            // field AppointmentLength is in minutes

            rec.Title = item.Title + " - " + item.AppointmentLength.ToString() + " mins";
            rec.StatusString = Enums.GetName<AppointmentStatus>((AppointmentStatus)item.StatusENUM);
            rec.StatusColor = Enums.GetEnumDescription<AppointmentStatus>(rec.StatusString);
            string ColorCode = rec.StatusColor.Substring(0, rec.StatusColor.IndexOf(":"));
            rec.ClassName = rec.StatusColor.Substring(rec.StatusColor.IndexOf(":")+1, 
                            rec.StatusColor.Length - ColorCode.Length-1);
            rec.StatusColor = ColorCode;                   
            result.Add(rec);
        }
        return result;
    }
}

The code is quite simple:

  1. We connect to the database using Entity Framework, run a LINQ query that extracts all appointment events between the start and end dates (using "EntityFunctions.AddMinutes" to create an end-date on the fly from the StartDateTime + AppointmentLength (in minutes)
  2. For each event returned, we create a DiaryEvent item and add the data table record information to it ready to send back.

Some things to note - first, FullCalander deals in dates in a UNIX format, therefore we had to run a conversion for this before querying. Second, I stored the color attribute of the "Staus" of the event in the "DESCRIPTION ANNOTATION" of the StatusENUM, and then used a method to extract the description, color code etc. The color code etc includes a css "class name" we will use later in the article to make the event item look a wee bit fancier...

CSS:

.ENQUIRY {
    
    background-color: #FF9933;
    border-color: #C0C0C0; 
    color: White;
    background-position: 1px 1px;
    background-repeat: no-repeat;
    background-image: url('Bubble.png');
    padding-left: 50px;
}
 
.BOOKED {
    background-color: #33CCFF;
    border-color: #C0C0C0;
    color: White;
    background-position: 1px 1px;
    background-repeat: no-repeat;
    background-image: url('ok.png');
    padding-left: 50px;
... etc...   

StatusENUM: 

  

Method to extract CSS class/color from Description attribute of StatusENUM:

public static string GetEnumDescription<T>(string value)
{
    Type type = typeof(T);
    var name = Enum.GetNames(type).Where(f => f.Equals(value, 
        StringComparison.CurrentCultureIgnoreCase)).Select(d => d).FirstOrDefault();
    if (name == null)
    {
        return string.Empty;
    }
    var field = type.GetField(name);
    var customAttribute = field.GetCustomAttributes(typeof(DescriptionAttribute), false);
    return customAttribute.Length > 0 ? ((DescriptionAttribute)customAttribute[0]).Description : name;
}

Ok, almost there, we need to take the list and put that into JSON format to send back to the Plugin ... this is done in a controller... 

public JsonResult GetDiaryEvents(double start, double end)
{
    var ApptListForDate = DiaryEvent.LoadAllAppointmentsInDateRange(start, end);
    var eventList = from e in ApptListForDate
                    select new
                    {
                        id = e.ID,
                        title = e.Title,
                        start = e.StartDateString,
                        end = e.EndDateString,
                        color = e.StatusColor,
                        someKey = e.SomeImportantKeyID,
                        allDay = false
                    };
    var rows = eventList.ToArray();
    return Json(rows, JsonRequestBehavior.AllowGet); 
} 

Finally (!) ... lets go back to our INDEX page, and add one line that tells the FullCalendar plugin where to go to get its JSON data...

Now when we run the application, we can click our INIT button, which will populate the database, and see the data coming through...

weehoo Smile | <img src=  ....

You recall earlier I talked about color, and ClassName - the plugin allows us to pass in a CSS class name, and it will use this to help render the event. In the CSS I showed earlier I added an icon image to the CSS decoration to make the event look visually better. To make this pass through, we add in the ClassName string...

And this is how it renders....

Thats superb, now lets look at client-side user functionality - how can the user interact with our diary?

Typically, one would expect to be able to select an event and get information on it, edit it, move it around, resize it, etc. Lets see how to could make that happen.

First, lets examine the information we sent along with the event. We can do this by adding adding a callback function when we initialise the plugin:

eventClick: function (calEvent, jsEvent, view) {
    alert('You clicked on event id: ' + calEvent.id
        + "\nSpecial ID: " + calEvent.someKey 
        + "\nAnd the title is: " + calEvent.title); 

The important param here is the first one, calEvent - from it we can access any of the data we sent through when we sent back the JSON records.

Heres how it looks:

Using this information you can hook in and use it to popup an edit form, redirect to a details window, etc. - your code chops are your magic wand.

To move an event around the plugin, we hook eventDrop.

eventDrop: function (event, dayDelta, minuteDelta, allDay, revertFunc) {
    if (confirm("Confirm move?")) {
        UpdateEvent(event.id, event.start);
    }
    else {
        revertFunc();
    }  
}  

The parameters dayDelta and minuteDelta are useful, as they tell us the amount of days or minutes the event has been moved by. We could use this to adjust the backend database, but there is another method I used.

I decided in this case to take the event object and use its information. When we create the event initially, it is set with the start/end date and time we give it. When the item is moved/dropped, that date and time change, however, the ID and the extra information we saved along with the event do not. Therefore my strategy in this case was to take the ID and the new start and end time and use these to update the database.

FullCalendar provides a "revertFunc" method that resets the event move to its previous state if the user decides not to confirm the event move.

On event move, I call a local script function "UpdateEvent". This takes the relevant data, and sends it by ajax to a controller back on the server:

function UpdateEvent(EventID, EventStart, EventEnd) {
    var dataRow = {
        'ID': EventID,
        'NewEventStart': EventStart,
        'NewEventEnd': EventEnd
    }
    $.ajax({
        type: 'POST',
        url: "/Home/UpdateEvent",
        dataType: "json",
        contentType: "application/json",
        data: JSON.stringify(dataRow)
    }); 
}

Controller:

public void UpdateEvent(int id, string NewEventStart, string NewEventEnd)
{
    DiaryEvent.UpdateDiaryEvent(id, NewEventStart, NewEventEnd); 
} 

Method called from controller:

public static void UpdateDiaryEvent(int id, string NewEventStart, string NewEventEnd) 
{
    // EventStart comes ISO 8601 format, eg:  "2000-01-10T10:00:00Z" - need to convert to DateTime
    using (DiaryContainer ent = new DiaryContainer()) {
        var rec = ent.AppointmentDiary.FirstOrDefault(s => s.ID == id);
        if (rec != null)
        {
            DateTime DateTimeStart = DateTime.Parse(NewEventStart, null, 
               DateTimeStyles.RoundtripKind).ToLocalTime(); // and convert offset to localtime
            rec.DateTimeScheduled = DateTimeStart;
            if (!String.IsNullOrEmpty(NewEventEnd)) { 
                TimeSpan span = DateTime.Parse(NewEventEnd, null, 
                   DateTimeStyles.RoundtripKind).ToLocalTime() - DateTimeStart;
                rec.AppointmentLength = Convert.ToInt32(span.TotalMinutes);
                }
            ent.SaveChanges();
        }
    }
} 

The important thing to note here is that the date format is sent in IS8601 format so we need to convert it. I also use a Timespan to calculate the new appointment length if any.

Event resizing, and updating the database appointment length server-side is done in a similar fashion. First, hook the event:

eventResize: function (event, dayDelta, minuteDelta, revertFunc) {
    if (confirm("Confirm change appointment length?")) {
        UpdateEvent(event.id, event.start, event.end);
    }
    else {
        revertFunc();
    } 
},  

You will notice that I have used the same controller and method to update the database - all in an effort to reuse code wherever possible! What happens is that if the update method sees that a new end date/time has been sent in, it assumes a RESIZE has happened and adjusts the "AppointmentLength" value accordingly, else it just updates the new start/date time.

if (!String.IsNullOrEmpty(NewEventEnd)) { 
    TimeSpan span = DateTime.Parse(NewEventEnd, null, DateTimeStyles.RoundtripKind).ToLocalTime() - DateTimeStart;
    rec.AppointmentLength = Convert.ToInt32(span.TotalMinutes); 
}

Now, thats great, and we have a lovely warm fuzzy feeling about making it happen, until we turn to look at the MONTH view....

Oh dear .... it renders every single event, and makes our calendar look rather messy... it would be better, for month view, if the control just showed a summary of appointment/diary events for each date. There is an elegant solution to this issue in "data sources". 

Full Calendar can store an array of event SOURCES. All we need to do is hook into the "viewRender" event, query what kind of view is active (day, week, month..), and based on this, change the source and tell the plugin to refresh the data.

First lets go back to our index.cshtml plugin init section and remove the reference to the data path as we will replace it with something else...   

To facilitate the new functionality we require, I created two variables to hold the URL path of each view. 

var sourceSummaryView = { url: '/Home/GetDiarySummary/' };
var sourceFullView = { url: '/Home/GetDiaryEvents/' }; 

What we are aiming to do is hook into the Click/change event of the view button group...

 

The way to do this is to drop in code that examines when the user clicks the buttons to change the view - this is "viewRender". Two parameters are passed, the first is "view" and that tells us what was just clicked: 

 

So depending on which view was clicked, we remove any data sources from the source array (by name), remove any events from the plugin, and finally assign one of the string variables we created earlier as the new data source which then gets immediately loaded.  

As our summary view holds slightly different information, we need to create a different method to extract data server side. This is almost the same as our previous query, with the exception that we need to extend our LINQ query to use GROUP and COUNT. Our objective is to group by date, and get a count of diary events for each day. Lets have a quick look at that method...

public static List<DiaryEvent> LoadAppointmentSummaryInDateRange(double start, double end)
{
    var fromDate = ConvertFromUnixTimestamp(start);
    var toDate = ConvertFromUnixTimestamp(end);
    using (DiaryContainer ent = new DiaryContainer())
    {
        var rslt = ent.AppointmentDiary.Where(
           s => s.DateTimeScheduled >= fromDate && 
           System.Data.Objects.EntityFunctions.AddMinutes(s.DateTimeScheduled, s.AppointmentLength) <= toDate)
           .GroupBy(s => System.Data.Objects.EntityFunctions.TruncateTime(s.DateTimeScheduled))
           .Select(x => new { DateTimeScheduled = x.Key, Count = x.Count() });
        List<DiaryEvent> result = new List<DiaryEvent>();
        int i = 0;
        foreach (var item in rslt)
        {
            DiaryEvent rec = new DiaryEvent();
            rec.ID = i; //we dont link this back to anything as its a group summary
            // but the fullcalendar needs unique IDs for each event item (unless its a repeating event)

            rec.SomeImportantKeyID = -1;  
            string StringDate = string.Format("{0:yyyy-MM-dd}", item.DateTimeScheduled);
            rec.StartDateString = StringDate + "T00:00:00"; //ISO 8601 format
            rec.EndDateString = StringDate +"T23:59:59";
            rec.Title = "Booked: " + item.Count.ToString();
            result.Add(rec);
            i++;
        }
        return result;
    }
}

As before, we need to convert the incoming unix format date. Next, because we are grouping by date, but we are storing a dateTIME, we need to remove the time part from the query - for this, we use the EntityFunctions.TruncateTime method, and chain the result of this into a sub select which gives us back a key field of date and a value of count.

Note that as this is summary information we don't have a key-id-field to link back to, but this is a problem for FullCalendar as it needs a unique ID for keeping track of events, so we assign an arbitrary one in this case of a simple counting variable ("i"). The other thing we need to do is because we stripped out the time part of the result to enable the grouping, we need to put it back in using ISO format.

Once the code is implemented, everything looks far better!

The last thing we are going to do is add a new event when a blank space on the calendar is clicked.

We will construct a quick bootstrap modal popup to capture an event title, date/time and appointment length: 

<div id="popupEventForm" class="modal hide" style="display: none;">
   <div class="modal-header"><h3>Add new event</h3></div>
  <div class="modal-body">
    <form id="EventForm" class="well">
        <input type="hidden" id="eventID">
        <label>Event title</label>
        <input type="text" id="eventTitle" placeholder="Title here"><br />
        <label>Scheduled date</label>
        <input type="text" id="eventDate"><br />
        <label>Scheduled time</label>
        <input type="text" id="eventTime"><br />
        <label>Appointment length (minutes)</label>
        <input type="text" id="eventDuration" placeholder="15"><br />
    </form>
</div>
  <div class="modal-footer">
    <button type="button" id="btnPopupCancel" data-dismiss="modal" class="btn">Cancel</button>
    <button type="button" id="btnPopupSave" data-dismiss="modal" class="btn btn-primary">Save event</button>
  </div>
</div> 

Next we will add a hook to our friendly plugin to show this modal popup when a day slot is clicked.

dayClick: function (date, allDay, jsEvent, view) {
    $('#eventTitle').val("");
    $('#eventDate').val($.fullCalendar.formatDate(date, 'dd/MM/yyyy'));
    $('#eventTime').val($.fullCalendar.formatDate(date, 'HH:mm'));
    ShowEventPopup(date); 
},

A small script method initialises the popup form, first clearing any input values hanging around and then setting focus to the first input box 

function ShowEventPopup(date) {
    ClearPopupFormValues();
    $('#popupEventForm').show();
    $('#eventTitle').focus(); 
}  

Finally we have script attached to the "save event" button to send the data back to the server via Ajax 

$('#btnPopupSave').click(function () {
    $('#popupEventForm').hide();
    var dataRow = {
        'Title':$('#eventTitle').val(),
        'NewEventDate': $('#eventDate').val(),
        'NewEventTime': $('#eventTime').val(),
        'NewEventDuration': $('#eventDuration').val()
    }
    ClearPopupFormValues();
    $.ajax({
        type: 'POST',
        url: "/Home/SaveEvent",
        data: dataRow,
        success: function (response) {
            if (response == 'True') {
                $('#calendar').fullCalendar('refetchEvents');
                alert('New event saved!');
            }
            else {
                alert('Error, could not save event!');
            }
        }
    });
}); 

If the server saves the record successfully it sends back 'True' and we tell the plugin to refetch its events.

The very last thing I want to address is double loading of data. When we are changing data sources using the viewRender callback, what happens is that on initial page load, the viewRender gets kicked off twice. To fix this, I added in a variable var CalLoading = true; at the top of the main script before the plugin is initialised, examine that when rendering the view, and reset it after the document is ready.  

 

So thats it! ... theres enough detail in this article to allow you, with very little effort, to include quite useful diary functionality into your MVC application. Full source code is included at the top of the article.

(PS: If you found this article useful or downloaded the code please let me know by giving a rating below!) 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

AJSON
Engineer
United Kingdom United Kingdom
Architect/engineer, student, always learning and refactoring my wetware. Happiest tucking into a big bowl of c# or python sprinkled with a crisp topping of Javascript...started with a single ZX80 a lifetime ago, now happily explore, build and create on interweb scale...



  • 7 Jun 2016 - "Upload large files to MVC / Web API using partitioning" - article of the day on ASP.net
  • 16 Sep 2015 - "Single Page Application with MVC and SammyJS" - article of the day on ASP.net
  • 01 Sep 2015 - "KnockoutJS nested arrays in MVC" - article of the day on ASP.net
  • 21 Aug 2015 - "Audit trail and data versioning with C# and MVC" - article of the day on ASP.net
  • 6 Oct 2014 - "Full Calendar – A Complete Web Diary System for jQuery and C# MVC" - article of the day on ASP.net



You may also be interested in...

Comments and Discussions

 
QuestionDelete events Pin
Heloisa Reis1-Jul-16 9:31
memberHeloisa Reis1-Jul-16 9:31 
AnswerRe: Delete events Pin
AJSON1-Jul-16 10:56
mvpAJSON1-Jul-16 10:56 
GeneralHelp to full calendar in mvc Pin
Dalwadi Tushar19-Jun-16 20:13
memberDalwadi Tushar19-Jun-16 20:13 
GeneralRe: Help to full calendar in mvc Pin
AJSON19-Jun-16 21:14
mvpAJSON19-Jun-16 21:14 
QuestionAdd New Event in date range for example start day is "2016/06/14", end date is "2016/06/17". Pin
Nadeem Badai13-Jun-16 19:46
memberNadeem Badai13-Jun-16 19:46 
QuestionUnable to modify jquery Pin
gopismiles6-Apr-16 16:19
membergopismiles6-Apr-16 16:19 
AnswerRe: Unable to modify jquery Pin
AJSON7-Apr-16 0:23
mvpAJSON7-Apr-16 0:23 
QuestionMessage Removed Pin
Member 119054121-Feb-16 3:41
memberMember 119054121-Feb-16 3:41 
QuestionMessage Removed Pin
MikeCHayes5-Nov-15 4:27
memberMikeCHayes5-Nov-15 4:27 
QuestionBootstrap validation to popup Pin
Member 115681043-Nov-15 14:29
memberMember 115681043-Nov-15 14:29 
AnswerRe: Bootstrap validation to popup Pin
AJSON14-Nov-15 6:57
mentorAJSON14-Nov-15 6:57 
GeneralMy vote of 4 Pin
hassanlou13-Sep-15 0:23
memberhassanlou13-Sep-15 0:23 
QuestionRemove unwanted string "12a" from all event Title Pin
renjithgovind8-Sep-15 21:23
memberrenjithgovind8-Sep-15 21:23 
AnswerRe: Remove unwanted string "12a" from all event Title Pin
AJSON8-Sep-15 23:53
mentorAJSON8-Sep-15 23:53 
GeneralRe: Remove unwanted string "12a" from all event Title Pin
renjithgovind9-Sep-15 0:31
memberrenjithgovind9-Sep-15 0:31 
GeneralRe: Remove unwanted string "12a" from all event Title Pin
renjithgovind9-Sep-15 0:43
memberrenjithgovind9-Sep-15 0:43 
GeneralMy vote of 5 Pin
letsdothisnow5-Sep-15 6:21
memberletsdothisnow5-Sep-15 6:21 
QuestionException thrown on .SaveChanges() Pin
Member 1186115931-Jul-15 3:19
memberMember 1186115931-Jul-15 3:19 
AnswerRe: Exception thrown on .SaveChanges() Pin
AJSON31-Jul-15 3:24
mentorAJSON31-Jul-15 3:24 
QuestionFullCalendar Form button to MVC controller action Pin
Member 1186115929-Jul-15 11:45
memberMember 1186115929-Jul-15 11:45 
AnswerRe: FullCalendar Form button to MVC controller action Pin
AJSON29-Jul-15 12:03
mentorAJSON29-Jul-15 12:03 
GeneralRe: FullCalendar Form button to MVC controller action Pin
Member 1186115930-Jul-15 5:37
memberMember 1186115930-Jul-15 5:37 
AnswerRe: FullCalendar Form button to MVC controller action Pin
AJSON30-Jul-15 5:44
mentorAJSON30-Jul-15 5:44 
GeneralThis is beautiful! thank you Pin
Gary Medina18-Jul-15 4:06
memberGary Medina18-Jul-15 4:06 
GeneralThank you! Pin
Bogdan Mihai Nicolae6-Jul-15 1:38
memberBogdan Mihai Nicolae6-Jul-15 1:38 
SuggestionIt is not responsive design, bad view on mobile Pin
Basharss5-Jul-15 2:43
memberBasharss5-Jul-15 2:43 
AnswerRe: It is not responsive design, bad view on mobile Pin
AJSON5-Jul-15 4:03
mentorAJSON5-Jul-15 4:03 
QuestionArgumentException Pin
Member 1179667827-Jun-15 9:11
memberMember 1179667827-Jun-15 9:11 
AnswerRe: ArgumentException Pin
Bogdan Mihai Nicolae3-Jul-15 3:02
memberBogdan Mihai Nicolae3-Jul-15 3:02 
QuestionAsk for Month View /Grouping summary Pin
Member 116899782-Jun-15 22:53
memberMember 116899782-Jun-15 22:53 
QuestionProblem with the JASON PAth Pin
auswis1-May-15 14:58
memberauswis1-May-15 14:58 
AnswerRe: Problem with the JASON PAth Pin
AJSON3-Jun-15 10:36
mentorAJSON3-Jun-15 10:36 
QuestionFull Calender jQuery in ASP.NET Pin
raj gaurav Srivastav28-Mar-15 8:20
memberraj gaurav Srivastav28-Mar-15 8:20 
AnswerRe: Full Calender jQuery in ASP.NET Pin
AJSON28-Mar-15 13:25
mentorAJSON28-Mar-15 13:25 
QuestionMoving and changing entries Pin
Jeffhome4312-Mar-15 6:29
memberJeffhome4312-Mar-15 6:29 
QuestionLogin details Pin
Jeffhome4312-Mar-15 5:57
memberJeffhome4312-Mar-15 5:57 
AnswerRe: Login details Pin
AJSON12-Mar-15 5:59
mentorAJSON12-Mar-15 5:59 
GeneralRe: Login details Pin
Jeffhome4312-Mar-15 6:01
memberJeffhome4312-Mar-15 6:01 
Questionwhat are the references for using fullcalendar Pin
Member 1146009010-Mar-15 20:04
memberMember 1146009010-Mar-15 20:04 
QuestionGreat work Pin
s.amittyagi2-Mar-15 21:59
members.amittyagi2-Mar-15 21:59 
AnswerRe: Great work Pin
AJSON3-Mar-15 0:08
mentorAJSON3-Mar-15 0:08 
AnswerRe: Great work Pin
Member 1146009010-Mar-15 20:37
memberMember 1146009010-Mar-15 20:37 
QuestionThx for free calendar and good article Pin
Babur Rizwan20-Feb-15 4:15
memberBabur Rizwan20-Feb-15 4:15 
QuestionStrange BUG with your source [vanilla build, no mods] Pin
Member 1146255118-Feb-15 20:04
memberMember 1146255118-Feb-15 20:04 
AnswerRe: Strange BUG with your source [vanilla build, no mods] Pin
AJSON18-Feb-15 23:26
mentorAJSON18-Feb-15 23:26 
SuggestionFull calendar bootstrap 3.0 Pin
Chattu Mitra8-Feb-15 21:53
memberChattu Mitra8-Feb-15 21:53 
QuestionDoes not work Pin
Member 113863805-Feb-15 8:35
memberMember 113863805-Feb-15 8:35 
QuestionCan use this for Persian calender? Pin
Ar.Gorgin3-Feb-15 20:01
memberAr.Gorgin3-Feb-15 20:01 
AnswerRe: Can use this for Persian calender? Pin
Basharss5-Jul-15 2:39
memberBasharss5-Jul-15 2:39 
AnswerRe: Can use this for Persian calender? Pin
AJSON5-Jul-15 4:04
mentorAJSON5-Jul-15 4:04 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160721.1 | Last Updated 20 Aug 2013
Article Copyright 2013 by AJSON
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid