NOTE: We’re now offering DHTMLX Scheduler .NET, an optimized version for ASP.NET apps.
This tutorial will lead you through the steps required to integrate dhtmlxScheduler into an ASP.NET MVC application. dhtmlxScheduler is a JavaScript scheduling calendar component, which can be used for a wide variety of use-cases connected to scheduling tasks. We will learn how to put this Ajax-based calendar on a web page, load events from .NET sever side and update them in the database when a user makes changes in the browser.
Download the final demo to get a better understanding of the solution we’re about to build.
Modern web apps impose ever higher demands on the user interface. In the case of standard controls, you can always use a built-in solution. However, with more complex controls – a calendar UI, for example – you are up against the problem. But here, third-party solutions can help. One of them is dhtmlxScheduler.
Preparation
First of all, you need to create a new project. Nothing specific, just an empty ASP.NET MVC project. Name it, for example, “My Calendar”. After that, create a database (or use any valid one) where you will save the calendar events. In the database, create the table “Events” with the following set of fields (all fields are mandatory):
|
While the DB tool is open, you can add some test data to the “Events” table. If you downloaded the final demo package, you can find there MyCalendar.mdf file which already contains the necessary table and data.
The next thing you need is the dhtmlxScheduler package, which can be downloaded from the dhtmlxScheduler homepage. Copy the content from the folder ‘codebase’ to the folder ‘Scripts’ of your project. The result of this step should look similar to the following:
Now that everything is ready, and all the necessary files are in place, you can proceed to the first step.
Step 1 – Initialization
First of all, you need to create a default view. Add a new controller – “CalendarController” – and create the “Index” view for it. Here is the content of Index.aspx file:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Index</title>
<script src="/Scripts/dhtmlxscheduler.js" type="text/javascript"></script>
<link href="/Scripts/dhtmlxscheduler.css" rel="stylesheet" type="text/css" />
<style type="text/css">
html, body
{
height:100%;
padding:0px;
margin:0px;
}
</style>
<script type="text/javascript">
function init() {
scheduler.init("scheduler_here",new Date(2010,6,1),"month");
}
</script>
</head>
<body onload="init()">
<div id="scheduler_here" class="dhx_cal_container" style='width:100%; height:100%;'>
<div class="dhx_cal_navline">
<div class="dhx_cal_prev_button"> </div>
<div class="dhx_cal_next_button"> </div>
<div class="dhx_cal_today_button"></div>
<div class="dhx_cal_date"></div>
<div class="dhx_cal_tab" name="day_tab" style="right:204px;"></div>
<div class="dhx_cal_tab" name="week_tab" style="right:140px;"></div>
<div class="dhx_cal_tab" name="month_tab" style="right:76px;"></div>
</div>
<div class="dhx_cal_header">
</div>
<div class="dhx_cal_data">
</div>
</div>
</body>
</html>
The default view loads .js and .css files of the dhtmlxScheduler and initializes a full-screen scheduler. The second and third parameters in the ‘scheduler.init’ command define default date and mode, which will be in the calendar just after initialization. Except for the first line, the code doesn’t have anything .NET MVC-specific. Actually, it’s fully taken from a standard scheduler example.
Now one more thing needs to be done – the updating of a default route. Switch the default route of the app to the newly-created controller in Global.asax.cs:
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Calendar", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
When all this is done and correct, you can run the app and see the next screen:
If you don’t see the screen above, most probably you didn’t copy the scheduler’s files to the folder ‘Scripts’ correctly, so check it again.
The calendar created with the dhtmlxScheduler has a clean and intuitive interface, and managing events is quite easy. To create new events, use the double click or click-and-drag commands. By clicking on tabs in the upper right-hand corner you can switch views: Day, Week, or Month.
Step 2 – Loading Data
The view we constructed in the previous step looks fine, but it doesn’t contain any data, so now let’s change this. First, add ‘Model’ to your application (just use “Model > Add > Add new item” and select “Data”,”Linq to SQL Classes”). To complete the process, drag-and-drop the “Events” table to the Model Designer, and then add one more action to the CalendarController.cs:
{
MyEventsDataContext data = new MyEventsDataContext();
return View(data.Events);
}
Define view for that action – Data.aspx:
<data>
<% foreach (var myevent in Model) { %>
<event id="<%=myevent.id%>">
<start_date><![CDATA[<%= String.Format("{0:MM/dd/yyyy HH:mm}",myevent.start_date) %>]]></start_date>
<end_date><![CDATA[<%= String.Format("{0:MM/dd/yyyy HH:mm}",myevent.end_date) %>]]></end_date>
<text><![CDATA[<%= myevent.text%>]]></text>
</event>
<% } %>
</data>
This template outputs not HTML, but XML data. For each event it will output a block of XML data. An extra bit of code is used to provide data in the necessary format. If you need to add extra fields to the model, just add extra tags to the view.
Slightly adjust the initialization code of your scheduler in Index.aspx:
function init() {
scheduler.config.xml_date = "%m/%d/%Y %H:%i"; // format of dates in XML
scheduler.init("scheduler_here", new Date(2010, 6, 1), "month");
scheduler.load("/Calendar/Data"); //path to the newly created action
}
</script>
Well, you’ve just configured the format of dates (it’s the same as in Data.aspx) and defined the path to action ‘Data’. At this point, the running application will look like this:
We’re halfway there. Just one more step, and we’re almost done.
Step 3 – Saving to the Database
After all the manipulations described above, we’ve built a scheduler which loads the events data from the database, but that’s not enough. Our next goal is to save changes made on the client side to the server. First of all, create one more action – CalendarController.cs:
{
String action_type = actionValues["!nativeeditor_status"];
Int64 source_id = Int64.Parse(actionValues["id"]);
Int64 target_id = source_id;
MyEventsDataContext data = new MyEventsDataContext();
Event myevent;
try{
switch (action_type)
{
case "inserted":
myevent = new Event();
myevent.start_date = DateTime.Parse(actionValues["start_date"]);
myevent.end_date = DateTime.Parse(actionValues["end_date"]);
myevent.text = actionValues["text"];
data.Events.InsertOnSubmit(myevent);
break;
case "deleted":
myevent = data.Events.SingleOrDefault(ev => ev.id == source_id);
data.Events.DeleteOnSubmit(myevent);
break;
default: // "updated"
myevent = data.Events.SingleOrDefault(ev => ev.id == source_id);
myevent.start_date = DateTime.Parse(actionValues["start_date"]);
myevent.end_date = DateTime.Parse(actionValues["end_date"]);
myevent.text = actionValues["text"];
break;
}
data.SubmitChanges();
target_id = myevent.id;
}
catch
{
action_type = "error";
}
return View(new CalendarActionResponseModel(action_type, source_id, target_id));
}
It seems that we have a lot of code, but it’s quite simple in its logic. In the first lines, we specify the type of action from the incoming request. Then, depending on the type, we inserted, deleted, or updated the data in the database. And after the DB operation was completed, we rendered a response to the client-side scheduler.
The file Save.aspx will look like this:
<data>
<action type="<%= Model.Status %>" sid="<%= Model.Source_id %>" tid="<%= Model.Target_id %>"></action>
</data>
The view shown above uses class ‘CalendarActionResponseModel’ to transfer the necessary information from the action to the view. In CalendarController.cs we add:
{
public String Status;
public Int64 Source_id;
public Int64 Target_id;
public CalendarActionResponseModel(String status, Int64 source_id, Int64 target_id)
{
Status = status;
Source_id = source_id;
Target_id = target_id;
}
}
Now update the Index.aspx one more time (add code that will link updates on the client-side scheduler with the action ‘Save’) :
function init() {
scheduler.config.xml_date = "%m/%d/%Y %H:%i";
scheduler.init("scheduler_here", new Date(2010, 6, 1), "month");
scheduler.load("/Calendar/Data");
var dp = new dataProcessor("/Calendar/Save");
dp.init(scheduler);
dp.setTransactionMode("POST", false);
}
</script>
If you launch the app now, the screen will look similar to the one from Step 2, but any changes or new events will be saved to the DB. Also, it will correctly restore after page reloading. So now we can proceed to the last step.
Step 4 – Improvements
The code we are using in ‘SaveController’ can be improved by using automatic bindings. In CalendarController.cs:
{
String action_type = actionValues["!nativeeditor_status"];
Int64 source_id = Int64.Parse(actionValues["id"]);
Int64 target_id = source_id;
MyEventsDataContext data = new MyEventsDataContext();
try{
switch (action_type)
{
case "inserted":
data.Events.InsertOnSubmit(changedEvent);
break;
case "deleted":
changedEvent = data.Events.SingleOrDefault(ev => ev.id == source_id);
data.Events.DeleteOnSubmit(changedEvent);
break;
default: // "updated"
changedEvent = data.Events.SingleOrDefault(ev => ev.id == source_id);
UpdateModel(changedEvent);
break;
}
data.SubmitChanges();
target_id = changedEvent.id;
}
catch
{
action_type = "error";
}
return View(new CalendarActionResponseModel(action_type, source_id, target_id));
}
To give your calendar a slicker and glossier look, or to customize the color scheme, use the online Skin Builder for dhtmlxScheduler [deprecated]. Select one of “Glossy” skins to get a more modern look for the calendar. When you’re done with the customization, download the skin package (.css files and images), and unpack it in the folder ‘‘Scripts’ (it will overwrite some old scheduler files).
The running app after those updates will produce the final look:
So let’s see what we’ve got: in just a few steps, we have implemented a web-based calendar that can be used in ASP.NET MVC and provide all the necessary functions: loading, saving, deleting, and updating events.
Of course, perfection knows no bounds. You can define extra fields, add/move calendar views, or redefine the scale and templates configuration (please refer to dhtmlxScheduler documentation). All these changes can be made simply by adding extra JavaScript commands in the “Index” view. There is no need for further updates in the “CalendarController.cs” code. So turn on your imagination and get going!
NOTE: If you’re using VB, please read this comment (many thanks to Brian).
Posted by Ivan Petrenko