Ext.Net - Calendar Component CRUD operations sample

Well this is a blog entry on request (the request is here). I received a request couple of days ago on one of my earlier ExtJs Calendar Component related posts to demonstrate remote Calendar CRUD operations in Ext.Net. So Gayan (the requestor), here goes the reply.

To begin with, Ext.Net ships with the Community version of the Calendar Component, which although being powerful, is limited when you compare it with the advanced features available in the Pro version of the Calendar Component. If you are not already aware, the Calendar Component has been donated to ExtJs by a company called Extensible owned by Brian Moeskau. Brian is one of the original developers for the ExtJs toolkit (that explains the beauty and power of the Calendar Component, Brian knows ExtJs inside out).

I have found the community version lacking for my needs, so I use the Pro version of the Calendar component outside the Ext.Net framework.

This link from Brian himself provides a good introduction to the Calendar functionality and is a must-read if you are using the Calendar component for the first time. Documentation for the component can be "cloned" from the official GitHub repository for the Calendar component here.

Gayan's request actually had 2 parts:

  1. Is it possible to have custom fields for the EventStore.

    The answer is yes. Calendar component's EventStore (and CalendarStore) are designed to be extensible. They expect some fields that should always be present (e.g. Id, Start time, End time and Title etc. for each Event). You are free to add any number of additional fields to the EventStore but you need to take care that the required fields are always present.

    Further you are allowed to rename the required fields by defining custom mappings. See the example below that should explain the process:

    var EM = Ext.calendar.EventMappings;
    EM.EventId.name = 'id';
    EM.CalendarId.name = 'cid';
    EM.Title.name = 'subject';
    EM.Notes.name = 'body';
    EM.StartDate.name = 'start';
    Ext.calendar.EventRecord.reconfigure(); 

    I have renamed the required fields above by defining custom mappings, and now I can add fields "id", "cid", "subject" etc. to the EventStore and any other custom fields I require.

    The custom mappings need to be defined after the Calendar scripts are loaded but BEFORE the EventStore is instantized. See the attached files for an example demonstrating how this can be done.

    In case of Ext.Net, it automatically adds the default Event Store fields, you need to set StandardFields="false" on the Event Store and then add the desired fields in the appropriate Reader. the attached code demonstrates all this. Please note that the attached code shows all fields that CalendarPanel supports, and can be renamed. You can add additional fields, but do not try to configure Mappings for the additional fields because that is not needed.

    Similar functionality is available for CalendarStore also, but only in the Pro version. You cannot rename/remap Calendar Store fields in the community version of the Calendar Component.

  2. The second part of the request is demonstration of the CRUD operations. Well, this part should have been easy if you have ever used HttpProxy for a RestFul ExtJs Store. Any actions against the Calendar component would have been posted to the handler automatically. Not to worry, let me quickly take you through the process.

    To begin with, you define a Store with a properly configured HttpProxy. Here's an example:

    <EventStore runat="server" ID="storeEvents" StandardFields="false" DateFormat="Y-m-dTh:i:s" AutoSave="true" Restful="true">
    	<Reader>
    		<ext:JsonReader IDProperty="id" Root="data" SuccessProperty="success" MessageProperty="message">
    			<Fields>
    				<ext:RecordField Name="id" />
    				<ext:RecordField Name="cid" />
    				<ext:RecordField Name="subject" />
    				<ext:RecordField Name="body" />
    				<ext:RecordField Name="start" Type="Date" />								
    				<ext:RecordField Name="end" Type="Date" />
    				<ext:RecordField Name="allDay" Type="Boolean" />
    				<ext:RecordField Name="reminderMinutes" />
    				<ext:RecordField Name="location" />
    				<ext:RecordField Name="url" />
    			</Fields>
    		</ext:JsonReader>
    	</Reader>
    	<Proxy>
    		<ext:HttpProxy Method="POST">
    			<RestAPI CreateUrl="CalendarHandler.ashx?op=add" ReadUrl="CalendarHandler.ashx?op=get"
    					DestroyUrl="CalendarHandler.ashx?op=delete" UpdateUrl="CalendarHandler.ashx?op=update" UpdateMethod="POST" />
    		</ext:HttpProxy>
    	</Proxy>
    </EventStore>

    Next you need to handle some standard events on the CalendarPanel (you can in fact handle these events at many places, in CalendarPanel, in CalendarView, in EventEditWindow, in EventEditForm and in EventStore itself, but I will recommend hooking to CalendarPanel events because events fired by all other components are automatically routed to and relayed by CalendarPanel). Here's the code for necessary event handling:

    {syntaxhighlighter brush: xml;fontsize: 100; first-line: 1; }<Listeners> <DayClick Handler="showEditWindow(this, {start: dt, allDay: allDay}, el);" /> <EventClick Handler="showEditWindow(this, record, el);" /> <EventMove Handler="record.commit();" /> <ViewChange Handler="if(this.editWin)this.editWin.hide();" /> <RangeSelect Handler=" showEditWindow(this, dates); this.editWin.on('hide', callback, this, {single:true});" /> <EventResize Handler="record.commit();" /> <EventDelete Handler="this.eventStore.delete(record);" /> </Listeners>{/syntaxhighlighter}
    Finally, you write your server-side handler for responding to CalendarPanel Ajax calls. Here's the prototype for the Handler's code:

    {syntaxhighlighter brush: csharp;fontsize: 100; first-line: 1; }switch (context.Request["op"]) { case "get": //You need to return data based on "start" and "end" parameters from Request. Use Fiddler to analyze how they are passed and then return the data appropriately. var l=new System.Collections.Generic.List<object>(); l.Add(new { id = 1, cid = 1, subject = "Meeting with Boss", start = DateTime.Now.AddDays(-5).ToString("s"), end = DateTime.Now.AddDays(-4.5).ToString("s"), reminderMinutes = 30, location = "Office Canteen" }); l.Add(new { id = 2, cid = 2, subject = "Picnic", start = DateTime.Now.AddDays(2).ToString("s"), end = DateTime.Now.AddDays(4).ToString("s"), reminderMinutes = 30, location = "Office Canteen" }); l.Add(new { id = 3, cid = 1, subject = "Another event", start = DateTime.Now.AddDays(5.7).ToString("s"), end = DateTime.Now.AddDays(6.9).ToString("s"), reminderMinutes = 0, location = "Office Canteen" }); context.Response.Write(serializer.Serialize(new { data = l })); break; case "add": //Add record to database here. //Server must return id property of new record, I am returning a dummy value. //Also ensure to return all submitted data back to the client //The code below just extracts the data from the request and sends it back to the client with a random id. System.Collections.Generic.Dictionary<string,object> obj=serializer.Deserialize<System.Collections.Generic.Dictionary<string, object>>(context.Request["data"]); obj["id"] = DateTime.Now.Ticks % 1000; context.Response.Write(serializer.Serialize(new { success = true, data = obj })); //For errors, the you should return the following and handle Store's exception event on client. //context.Response.Write(serializer.Serialize(new //{ // success = false, // message = "Reason why it failed..." //})); break; case "update": //Update data to db here. Again Fiddler should be your friend in case you are not sure what's gets passed-in from client. context.Response.Write(serializer.Serialize(new { success = true })); break; case "delete": //Delete record from db here. Again Fiddler should be your friend in case you are not sure what's gets passed-in from client. context.Response.Write(serializer.Serialize(new { success = true })); break; }{/syntaxhighlighter}

The completely functional and working demonstration of the CRUD operations for the CalendarPanel together with examples of modifying the field names for the EventStore is attached with this post below. There are a couple of files, Calendar.aspx contains all the front-end markup and code required for handling CalendarPanel in Ext.Net, CalendarHandler.ashx is the backend code for the CalendarPanel CRUD operations.

If you are a native ExtJs user, you can find a fully functional demo for remote CRUD operations for the CalendarPanel in its GitHub repository link posted above.

I hope this blog post tells you everything you need to know for working with CalendarPanel Gayan...

 

AttachmentSize
Binary Data Calendar.aspx6.41 KB
Binary Data CalendarHandler.ashx2.75 KB

Comments

what should i say??? nothing to say rahul SUPERB SUPERB SUPERB. it's incredible and you are a great solution developer i have been waiting long time for usefull reply from some others but they didn't even understood the question of mine. but after reading your super post and code i think i have 100% clear idea. thank you very much rahul for your valueble time for one of your favorite blog reader.

rahul's picture

Thanks Gayan for your kind remarks... I am glad my posts are found useful by the readers....

You might be interested to know that the Ext.NET Calendar Pro component has been developed and should be available directly from Ext.ensible at approx the same time as the official Calendar Pro v1.0 final release. A beta may be available for testing soon. 

Here's a few test demos we've been working on. 
http://calendarpro.ext.net/

Thanks for posting this info on the <ext:Calendar>.

Hope this helps.

rahul's picture

Hi Geoff, thanks for providing the information (I was expecting an Ext.Net Calendar Pro), so great work again by Ext.Net team...

BTW, it would be great to provide a mechanism for defining CalendarMappings and EventMappings both in code as well as mark-up.

EXT.NET superb and im a fan of this framwork

Hi Rahul,

Thanks for the Excellent Post, I tried your sample it works but save button event is not fired. Can you point me what could be the possible reason?

rahul's picture

Hi Sachin, can you please elaborate a bit? Which Save button are you referring to? Please note that you cannot subscribe directly to click event of buttons on Event Edit Window and Form without overriding CalendarPanel code.

Well I dont want to override the code. The EventAdd listner in the code is not fired. While it works completely  http://examples.ext.net/#/Calendar/Overview/Basic/ here.

Thanks for your attention.

rahul's picture

That's not the Save event on button, but eventadd/eventupdate event on CalendarPanel/EventEditWindow.

sorry for confusion I am talking of EventAdd event only.

rahul's picture

Hi Sachin, I cannot imagine a reason for the event not firing. And its hard to guess without looking at the actual code.

Well its your code only.. same without any change.

rahul's picture

Hi sachin, sorry for the delay in response. I tested the code again, and placed an alert in "eventadd" handler. It gets called and everything works as expected. The ajax request to CalendarHandler.ashx also gets triggered.

thank you so much rahul for share with me this webiste

Hi Rahul,

I am new for ExtJs can you plz tell me how can I save and retrive data from mysql by using php in Extjs calendar.

rahul's picture

Hi Vivek, if you are new to PHP/MySql, then ExtJs Calendar is a slightly difficult exercise for the beginning. However, if you are comofrtable using MySql from PHP, then this example should give you enough details:
http://ext.ensible.com/deploy/dev/examples/calendar/remote.html

It stores data in Session, but you can easily change that to use MySql instead. 

Thanks Rahul for the quick response  but I know php and mysql but fail to understand session_db.php code do you have any example code or anything that helps me.

rahul's picture

Hi Vivek, I do not have any code samples for Calendar component in PHP but I would insist, you can easily adapt session_db.php code to work with MySql if you are familiar with working with PHP and MySql together.

hi Rahul. ive tried to run the code but none of the events are showing even after adding new ones. what could be the problem

rahul's picture

Please ensure you are sending valid id from server after a new event is saved. Other than that, I will need to see it live somewhere to figure out the problem (ensure you do not have any js errors on your page).

Dear Rahul, 

i have la little problen and hope thatu  will be able to help me in...

i am trying to do an ext,net calender customed, that taked events from database , with more fields than the class events , and crete normally the calender. how can i find or customise the form that ,on click on the calender gives the edit , add , delete, update calender.

how can i customise this form so i can be able to add my other event fields ? if any links or any solution, would be glad to listen..

regards,  

Microsoft JScript runtime error: Unable to get value of the property 'getTime': object is null or undefined

rahul's picture

Hi Kev, I dont think there is a reference to a method called "getTime" anywhere in the above sample code.

 Hi Rahul,

I am new for ExtJs can you plz tell me how can I save and retrive data from sql server by using webservices in Extjs calendar.

Thanks 
chandan

rahul's picture

Hi chandan, CalendarHandler.ashx attached with the blog post contains enough comments to guide you on how to save and retrieve data from any data source. I would not suggest using a Web-service for this purpose as web-services are supposed to return xml (you can return json from a web-service but that's hacky), and you would find it easier to deal with json while working with ExtJs (or in fact, any javascript framework).

hi rahul,

 I had written WCF Rest style services for CURD operation. i am not able to implement this. if you kindly help me how to implement WCF rest style services with ext net calendar. it will help me lot. please fied the below code.

var eventStore = Ext.create('Extensible.calendar.data.EventStore', {
        autoLoad: true,
        proxy: {
            type: 'rest',
            url: 'http://servername/RestServices/RestServiceImpl.svc/view/',  ' this is i am calling 
           noCache: false,            
            reader: {
                type: 'json',
                root: 'data'
            },            
            writer: {
                type: 'json',
                nameProperty: 'mapping'
            },            
            listeners: {
                exception: function(proxy, response, operation, options){
                    var msg = response.message ? response.message : Ext.decode(response.responseText).message;
                    // ideally an app would provide a less intrusive message display
                    Ext.Msg.alert('Server Error', msg);
                }
            }
        },

When I am trying to invoke this services using fiddler I am getting proper response. When I am try to call using Remote.js code as above I am getting error.

Please find the  attached error screen short

thanks
chanda kumar

sorry i am uploaded wrong image 

rahul's picture

Hi Chanda, the screenshot tells it all, the HTTP method is not allowed:
http://stackoverflow.com/questions/41155/wcf-service-returning-method-not-allowed 

Hi.

Testing your code using Ext.Net 2.0 found this error:

Type 'Ext.Net.CalendarPanel' does not have a public property named 'GroupStore'.