ExtJs - Dynamic Calendars for the Calendar Component

If you haven't yet seen the Calendar Component for ExtJs, you might well want to check it here first, and then see it in action (an example is below in this blog post, ExtJs example for Calendar component is here).

Although the Calendar component's Pro edition is planned in February 2011, we have already started using the Pro features for one of our enterprise apps in a major way. And my first assignment for the Calendar component was making the available Calendars dynamic. A bit of a background to explain what I mean...

Multi Calendar SupportThe Calendar component supports multi-calendar feature. You actually pass-in 2 stores to the Calendar component, one specifying the available Calendars and the other with the events. Each event is associated to one Calendar and each Calendar can be assigned a Color. This color is used for rendering all events belonging to that Calendar (see the screenshot on the right for an example).

Now the Calendar component does not support dynamic Calendars (i.e. the ability of adding/removing/modifying Calendars, or changing a Calendar's color-code) out-of-the-box. For our application, we needed to provide users with the ability to manage Calendars individually for each user.

Below is a simplified version of what I produced for my team (Click here to open the example in a new tab):

 

 

Click on the "Manage Calendars" button on the left bar to add/remove Calendars dynamically or change their color codes. Then try clicking on the Calendar surface to add/edit events for the newly added Calendars.

The following code is what is needed for the dynamic Calendar feature. I have modified the code to integrate easily with the official Calendar app example so that you can see the dynamic Calendar feature at work with the full power of the Calendar component. You can easily change the namespaces below to use for your application.

 

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; } App.calendarWindowMenu = new Ext.menu.Menu({ cls: 'x-calendar-list-menu', items: [new Ext.ensible.cal.ColorPalette({ handler: function(palette, colorId) { var record = App.calendarPanel.calendarStore.getAt(App.calendarWindowMenu.recordIndex); record.set('ColorId', colorId); App.calendarWindowMenu.hide(); App.calendarWindowDataView.refreshNode(App.calendarWindowMenu.recordIndex); } }), new Ext.menu.Item({ text: 'Delete', iconCls: 'no-icon', handler: function() { Ext.Msg.confirm('Action confirmation', 'Please ensure no Event is associated to this Calendar. Continue with deletion?', function(btn) { if (btn == 'yes') { App.calendarPanel.calendarStore.removeAt(App.calendarWindowMenu.recordIndex); } }); } })] }); App.calendarWindow = new Ext.Window({ title: 'Manage Calendars', width: 325, height: 400, modal: true, layout: 'fit', closeAction: 'hide', bodyStyle: 'background-color: white', items: [new Ext.DataView({ store: App.calendarPanel.calendarStore, cls: 'x-combo-list', style: 'background-color: white; padding: 5px', itemSelector: '.x-combo-list-item', selectedClass: 'x-combo-selected', overClass: 'x-combo-selected', autoScroll: true, tpl: new Ext.XTemplate( '<div>Click on a Calendar to change its color or remove it.</div>', '<tpl for=".">', '<div class="x-combo-list-item" style="vertical-align: middle">', '<div class="x-cal-{ColorId}">', '<div class="mail-calendar-cat-color ext-cal-picker-icon" onmouseover="Ext.get(this).addClass(\'mail-calendar-cat-color-over\');" onmouseout="Ext.get(this).removeClass(\'mail-calendar-cat-color-over\');">&nbsp;</div>', '</div>', '<div>{Title}</div>', '</div>', '</tpl>', '<div class="x-clear"></div>' ), multiSelect: false, listeners: { click: function(view, index, node, e) { App.calendarWindowMenu.recordIndex = index; App.calendarWindowMenu.show(Ext.get(node)); } } })], buttons: [{ text: 'Add Calendar', handler: function() { Ext.Msg.prompt('Enter name', 'Enter calendar name:', function(btn, text) { if (btn != 'ok') return; if (App.calendarPanel.calendarStore.findExact('Title', text) != -1) { Ext.Msg.alert('Invalid input', 'A Calendar with the same name already exists.'); } else { App.calendarPanel.calendarStore.loadData({ calendars: [{ title: text, color: 1}] }, true); } }); } }, { text: 'Save Changes', handler: function() { Ext.Msg.alert('Save', 'Save changes to the Calendars on the server here.'); App.calendarPanel.calendarStore.commitChanges(); App.calendarWindow.hide(); } }, { text: 'Cancel', handler: function() { App.calendarPanel.calendarStore.rejectAllChanges(); App.calendarWindowDataView.refresh(); App.calendarWindow.hide(); } } ] }); App.calendarWindowDataView = App.calendarWindow.items.items[0]; });{/syntaxhighlighter}

 

 

The above code uses an Ext.DataView to display a list of available Calendars together with their current color. Most of the code above is boiler-plate ExtJs code, except choosing the color for the Calendar in a menu. I had to dig deep into the Calendar component framework to understand how it handles colors for the Calendars.

Calendar color paletteTo provide you some idea, the Calendar framework comes with a built-in support of 32 configurable colors for the Calendars. You can choose the colors via the ColorPalette available in Calender Pro. However, the built-in framework shows you ColorPalette inside a CalendarList component (the one in the left bar in the above example), and shows other options while choosing the color. Moreover, it only allows you to change color of an existing Calendar but does not allow you to add new Calendars.

The code above allows you to manipulate available Calendars dynamically providing options for adding/removing or changing colors for Calendars. As mentioned, the code renders the available Calendars in a DataView. Clicking any row of the DataView pops-up a Menu allowing you to change the color for the Calendar, or remove it altogether. You can easily add any desired MenuItem to the Menu to provide more custom options for any Calendar.

You can override the default available 32 colors for a Calendar (and the color palette) through css. Have a look at the "resources/css/calendar-colors.css" file in the Calendar package to know the css classes you need to override for changing the available colors.

 

Let me tell you another aspect of our application regarding the multi-calendar support. The Calendar component uses colors for events to distinguish between various types of events, and calls each type a Calendar (thus calling the whole concept multi-calendar support).

For our application, we instead call each type a Category. So, colors are used for distinguishing between the types of events on a single Calendar. We allow our users to open multiple Calendar instances in Tabs to provide a more real multi-calendar support, where users can manage Categories for each Calendar independently.

 

The code for the above example (html, css and javascript) is attached below. I would again like to acknowledge that I modified the Calendar test application that ships with the Calendar Pro version to create the example above.

 

Web 2.0: 
AttachmentSize
HTML icon dynamic-calendars.html1.72 KB
File dynamic-calendars.js.txt23.72 KB
File test-app.css1.41 KB

Comments

I'm really Interesting your blog posts. and have question. Does calender control (ext.net) can use to bind our own data?? (not event data) can you please make a blog post how to work EXT.NET calender control with serverside databinding all CRUD operations

thanks.

rahul's picture

Hi Gayan, I am glad my blog posts have been found to be useful. Yes, you can use Ext.Net's Calendar Control to bind your own data. I am really running short of time these days, you you might actually need to wait sometime before I write the requested blog post.

rahul's picture

Hi Gayan, I took time out today, and wrote the requested blog post. It's available here:
http://www.rahulsingla.com/blog/2011/01/ext-net-calendar-component-crud-operations-sample

I hope this answers everything you need to know about the CalendarPanel... 

Thanks Rahul for your valueble time and really appreciate.

Hi Rahul, I hope you are fine.

I am investigating your example in order to see if it cam be used in my application.

Can you give me some guidance about how to save the Calendar Data in a MySQL Databade (using PHP) once you click one of the "Save" buttons?? Or maybe save all the dataStorage once you finished working with it?

I had no problem in loading my data from MySql to your Calendar, by dinamically writing the Ext.ensible.sample.EventData object. But I don't know how to save the data.

By the way, I'm a newbie in ExtJS, but I have enough experience in Javascript, PHP and MySQL (among many other langs)

I hope you can help me with this.

Many thanks in advance.

Kind regards,
Nicolas Castro

rahul's picture

Hi Nicolas, you use ExtJs' REST API for saving Calendar data back to your server-side DBMS. Check this example from official CalendarPanel component's pckage:

https://github.com/bmoeskau/Extensible/blob/master/examples/calendar/remote.html

Thank you very much Rahul!!! I will check it and let you know.
Thank yoy very much!!

Hi again Rahul, I hope you are fine.

Regarding the issue I asked you about, I spent some time reiewing the example you refeered.

Is there any documentation that explain the code areas that I check? Because there are some points that I'm not clear about.

For example, I asume that my database access code must be inserted in the file session_db.php, but there are some $_SESSION variables there that I'm not clear what are they used for exactly.

Here:

    // fake a database pk
    public function pk() {
        return $_SESSION['pk']++;
    }
    // fake a resultset
    public function rs() {
        return $_SESSION['rs'];
    }
    public function insert($rec) {
        array_push($_SESSION['rs'], $rec);
    }
    public function update($idx, $attributes) {
        $_SESSION['rs'][$idx] = $attributes;
    }
    public function destroy($idx) {
        return array_shift(array_splice($_SESSION['rs'], $idx, 1));
    }

I asume that I must put my INSERT/UPDATE code there, but what I should do with the $_SESSION variables once I do that? The $attributes variable, what is it content? I assume that it came with the new Event data to be inserted un the DB, but in what format? JSON?

I keep geting the error "The remote action could not be completed" when I select "Simulate server error" check box. What does that means? I am runing the example in a MySQL+PHP+apache server.

In th eother hand, how can I mix the main example (the one without persistence) with this one?

I appologize for being so ignorant, but I want to learn and I really like your work with ExtJS!!

I really think that your product can fit my application, but I need to make it wok first, hehe...

thank you very much for your help

kid regards,
nicolas

Dear Rahul, don't need to answer last message. I alreadyy make it work!!

I will evaluate and let you know if I'm going into production with it.

kind regards,
nicolas

rahul's picture

Thanks Nicolas for letting me know. I was just about to get down to study your question and answer it... Good to know that you have it working.

But please note that Calendar is NOT my poduct. It's produced by Extensible owned by Brian Moseiaku (one of the original foounders of ExtJs).

Hello Nicolas,

It Would be nice if you told how you fixed the PHP, MySql setup. So others can benefit aswell.

Thanks,

Luis Roman

Hi Luis, how are you?Sorry for my late responce.

EHre is my session_db.php code:

I hope it helps you.

regards
nicolas

rahul's picture

Hi Nicolas, I have edited your comment and added the code as an attachment (helps in maintaining the sanity of the page). Thanks for sharing your code.

Hello my name is Leandro. first of all thank you very much for the contribution. I wanted to ask if you could give us the code of the table definition for mysql and the connection code include ('.. /.. /.. /.. / Include / functions.php'). From already thank you very much.
Greetings.

rahul's picture

Hi Leandro, I don't think the sample on this page is mysql backed or uses php. The test data is built entirely in javascript, can you please cross-check whether the files you are requesting are related to this blog post only.

Hello!
Thank you very much for the calendar! you helped me a lot!
I have a question. In the last day of the calendar (for example, 2 July 2011), I add an event: 07/02/11 16:00 - 03/07/11 16:00 "take care of the cat". But
this event disappears. If you go to the next month (July), the event will be visible. I found that if I put the start date 2/7/11 12:00, then the event does not disappear. So it should be? Why then do we see all the events of the first day of the month (07/29/2011)?

rahul's picture

Are you doing it all client-side (or server is involved too)?? I would check the timezone settings for the browser and the server.

Hello Rahoul, how are you.

In the final stages of testing I found that when using IE8 it drops me this error:

_renderAsAllDay is undefined in extensible_all.js

Do you have any idea that wht could be happening? I tried your example in IE8 and it works fine, and I havent made modifications to the code I downloaded.

I appretiate your help.
thank you very much!!

rahul's picture

Hi Nicolas, most probably that should be an error with the Calendar itself (or maybe due to incorrect field mappings). I have used this code successfully with IE 7/8/9. I was on a vacation and back now and have piles of work to clear up. I am afraid I might not be able to look into this in the short term. Can you please check the code against the latest version of Calendar available from github?

Hi Rahoul, I browsed this web: https://github.com/. But I couldnt find anything related to extjs calendar. Where can I found the latest code? I tryed the link where I downloaded the firts time buy it is offline.

I appretiate your help, because Im quite stuck with this!
Thank you very much!

rahul's picture

Hi Nicolas, here's the official code for ExtJs Calendar:
https://github.com/bmoeskau/Extensible/ 

This is a great article, but how can I load data to the calendar dinamically?

I mean, how can I load my data from MySql to the Calendar?
Thanks!

I mean how can i dinamically load data in this part:

Ext.ensible.sample.EventData = {

Hi, is me again.

What happen whit the reminder? I can´t find code or documentation about the reminder. Do you have a link or something to read?

Thanks!

I was looking here: http://ext.ensible.com/deploy/dev/examples/

but seems that in all that examples doesn´t work...

rahul's picture

Hi Jaro, I am not sure what you mean, If you see this sample application, while adding/editing an event, you can click on "Edit details" button where you can specify the Reminder time for the event. Events with Reminder set are shown with a bell during view. What else do you need?

Hi rahul, I know what you mean. But I thought that when the time is in the exact hour that the reminder was set, you can throw an event or function or callback or something. Is that possible?

I like the clock on the view is beautifull, but I need to do something with the reminder like a real reminder. I don´t know if I explain myself correctly, please let me know if you don´t understandme.

Regards,

Jaro.

rahul's picture

Hi Jaro, I do not think that is possible out-of-the-box in the Calendar component. I have done it in my code (along with other things like smart caching of events which fetch events selectively from server as needed and cache them locally as views or date ranges change).

The easiest option for you I think would be to subscribe to the Calendar store's load/add events and manually have a DelayedTask or setTimeout to execute for all events from today that have reminders at appropriate time.