Creating Event Calendar with dhtmlxScheduler and AngularJS

| Comments (49)

AngularJS is a modern JavaScript framework that allows creating rich client-side apps in a fast and productive way. It goes without saying that AngularJS is convenient and powerful in working with HTML. However, it doesn’t have ready to use complex UI components yet. In this article we’ll try to partially eliminate this drawback by showing how to add support of dhtmlxScheduler, a Google-like event calendar, for an AngularJS app.

Download dhtmlxScheduler to add a powerful event calendar to your app

AngularJs Event Calendar with dhtmlxScheduler

You can check the online demo of a ready app or just grab the sources of the app from GitHub.

Adding dhxScheduler Directive

In order to build a custom HTML component in AngularJS we need to create a new directive. So let’s start integrating the Scheduler from writing a directive for it. For this purpose we need to create a .js file with the following content:

app.directive('dhxScheduler', function() {
  return {
    restrict: 'A',
    scope: false,
    transclude: true,
    template:'<div class="dhx_cal_navline" ng-transclude></div><div class="dhx_cal_header"></div><div class="dhx_cal_data"></div>',

    link:function ($scope, $element, $attrs, $controller){
      //adjust size of a scheduler
      $scope.$watch(function() {
        return $element[0].offsetWidth + "." + $element[0].offsetHeight;
      }, function() {

      //styling for dhtmlx scheduler

      //init scheduler
      scheduler.init($element[0], new Date(), "month");

The above code may look a bit complicated, but the things the code produces are rather simple:

  • the code defines a new directive which can be used as a custom attribute
  • when the new directive (dhxScheduler) is initialized, it will create the dhtmlxScheduler object with the default settings
  • the watcher function will be constantly checking the size of scheduler’s container and will resize the component when the size of HTML container changes.

For creating an instance of dhtmlxScheduler on a page it’s actually enough to write the above code and place the directive somewhere on the page. If we want to create a simple app with a scheduler inside, the HTML code structure shown below is needed:

<!doctype html>
<html lang="en" ng-app="schedulerApp">
  <meta charset="utf-8">
  <title>Angular Calendar demo</title>

  <link rel="stylesheet" href="css/app.css">
  <link rel="stylesheet" href="lib/scheduler/dhtmlxscheduler.css">

  <script src="lib/angular/angular.min.js"></script>
  <script src="lib/scheduler/dhtmlxscheduler.js"></script>
  <script src="js/app.js"></script>
    <div dhx-scheduler style="height:350px; width:600px;">
        <div class="dhx_cal_prev_button">&nbsp;</div>
        <div class="dhx_cal_next_button">&nbsp;</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>    

As you can see, we’ve included the .js and .css files of both the AngularJS framework and the dhtmlxScheduler component. Our newly created dxhScheduler directive is used in the code of the page. The dhx-scheduler attribute is used to trigger the directive and to initialize the scheduler component. The HTML tags inside of dhx-scheduler div container are necessary to define the buttons on the top bar of the scheduler.

When you open a page with the described HTML code in a browser, you will see an event calendar component ready to be used:

dhtmlxScheduler - Using with AngularJS

Linking to the Scope

For now our AngularJS event calendar just renders itself, which is good but not quite useful yet. Let’s link the scheduler’s state and content to the scope in order to expand the app’s functionality. For this purpose we need to extend the link method of the directive as follows:

link:function ($scope, $element, $attrs, $controller){
  //default state of the scheduler
  if (!$scope.scheduler)
    $scope.scheduler = {};
  $scope.scheduler.mode = $scope.scheduler.mode || "month";
  $ = $ || new Date();

  //watch data collection, reload on changes
  $scope.$watch($, function(collection){
    scheduler.parse(collection, "json");
  }, true);

  //watch mode and date
    return $scope.scheduler.mode + $;
  }, function(nv, ov) {
    var mode = scheduler.getState();
    if ( != || nv.mode != mode.mode)
      scheduler.setCurrentView($, $scope.scheduler.mode);
  }, true);

  //size of scheduler
  $scope.$watch(function() {
    return $element[0].offsetWidth + "." + $element[0].offsetHeight;
  }, function() {

  //styling for dhtmlx scheduler

  //init scheduler
  scheduler.init($element[0], $, $scope.scheduler.mode);

Let’s see what was added. The top block checks if there are settings for the scheduler in the scope. If there are no such settings, they will be created with default values.

After the top block, two new watch instructions follow. The first instruction will monitor the state of data collection and reload the scheduler with new data when the collection is changed. The second instruction will change the scheduler’s settings (mode and date) when the related parameters are changed in the scope.

Finally, we have slightly adjusted the scheduler.init command. Now it uses values from the scope as initial view and date values.

After applying all these changes we can do the following:

  • We can place custom buttons on the page. Clicking the first button will change the displayed date and clicking the second button will switch the mode of events view in the calendar:

        <button ng-click="scheduler.mode = 'week'">Week</button>
        <button ng-click=" = new Date()">Week</button>
  • We can load data from the scope to the scheduler:

    app.controller('MainSchedulerCtrl', function($scope) {
      $ = [
        { id:1, text:"Task A-12458",
          start_date: new Date(2013, 09, 30, 9, 0),
          end_date: new Date(2013, 09, 30, 16, 0) },
        { id:2, text:"Task A-83473",
          start_date: new Date(2013, 09, 28, 9, 0),
          end_date: new Date(2013, 09, 30, 16, 0) }


       <div dhx-scheduler data="events" style="height:350px; width:600px;">
  • We can use some input on the page to filter the scheduler:

       <div dhx-scheduler data="events | filter:search" style="height:350px; width:600px;">

Thus we have a scheduler populated with data. The scheduler has the functions of date and mode changing, and data filtering. Next we can customize the appearance of events in the scheduler.

The Look of Events

Well, we can now define the content and appearance of event bars in the calendar. dhtmlxScheduler provides JavaScript API for templating and we can take the advantage of this API to specify the look of events in our calendar. The code below will define one more directive which can be used to define the scheduler’s templates:

app.directive('dhxTemplate', ['$filter', function($filter){
  scheduler.aFilter = $filter;

  return {
    restrict: 'AE',

    link:function($scope, $element, $attrs, $controller){
      $element[0].style.display = 'none';

      var template = $element[0].innerHTML;
      template = template.replace(/[\r\n]/g,"").replace(/"/g, "\\\"").replace(/\{\{event\.([^\}]+)\}\}/g, function(match, prop){
        if (prop.indexOf("|") != -1){
          var parts = prop.split("|");
          return "\"+scheduler.aFilter('"+(parts[1]).trim()+"')(event."+(parts[0]).trim()+")+\"";
        return '"+event.'+prop+'+"';
      var templateFunc = Function('sd','ed','event', 'return "'+template+'"');
      scheduler.templates[$attrs.dhxTemplate] = templateFunc;

This code defines the dhxTemplate directive. This directive can be used both as an attribute or as a custom tag. The content of the directive will be converted to JavaScript function and used as a template of the scheduler. To specify the template for the scheduler, you can use the syntax very similar to that of the native AngularJS templates. This syntax implies the use of the {{}} expressions as placeholders in the template’s text.

For example, we can add the following code on the page:

<div dhx-template="event_bar_text">
   <strong>#{{}}</strong>: {{event.text | uppercase}}

The above code will produce the result as follows:

dhtmlxScheduler and AngularJS - Custom Template

The dhx-template attribute’s name (“event_bar_text” ) is the name of scheduler’s template which needs to be defined. Check the full list of templates in the documentation.

Please notice that the template defined in such a way won’t have the full functionality of a native AngularJS template. Take into account the following points:

  • You need to use the format of the type {{event.some}} to define the template. Instead of “some” place the necessary property of event object. “event.” in our example is a fixed part that is used only by the scheduler to define the event’s property. It is not related to the current scope.
  • You can’t use the scope’s variables inside of the template.


Summing Up

So although there are no complex UI components in Angular JS, we can add such a component with the help of some additional code. Thus, by using the two directives defined above (dhxScheduler and dhxTemplate) you can easily add a rich-featured event calendar on the page and customize its appearance.

download scheduler

The above described functionality of the scheduler component is just a tip of the iceberg. dhtmlxScheduler has a rich API and lot of properties and events. It makes no sense to wrap all of them into AngularJS directives, as you can easily make any necessary calls from Angular controller’s code (check the details of the dhtmlxScheduler API in the documentation).

The simplicity of integration shows the flexibility of both AngularJS and dhtmlxScheduler. While both of them are independent solutions, with a bit of glue code they work together in a neat way. By using the above code you can get a Google-like event calendar for your AngularJS web app.


  1. Iris January 12, 2014 at 5:05 pm


    Really nice example, but could you maybe give some pointer on how to load events from the database? I can not seem to find anything about this..


    • irth orbits February 5, 2014 at 1:34 am

      Great tut! Timely for me, can’t wait to try it.

      @Iris, you might create a service object called events, events could then be injected into your view’s controller function as an argument and then you would expose them via /* $ = events */ to the calendar. Alternatively, you might use resolve from your routing to dump the event data. I think the Angular docs will do a better job of explaining your many options for different database hookups. I really love Firebase IO ;).

  2. Kevin March 27, 2014 at 10:42 am

    Great blog.
    Can you make an example for timeline view scheduler? it would be a great help for me. thanks


  3. laxman April 16, 2014 at 12:40 pm

    the scheduler control is nice,but could you give some example on how to restrict the event section update in the scheduler

    • Ivan April 17, 2014 at 2:42 pm

      Sorry, I’m not quite sure what do you mean by “restrict section update”. Still, you can try to add something like:

      scheduler.config.readonly = true;

      in the js code, after scheduler.init() call.
      If you need more precise control, check the next article:

  4. Tuan April 16, 2014 at 1:01 pm

    hi, I added the callback for onAfterTaskUpdate event such as

    gantt.attachEvent(“onAfterTaskUpdate”, function(id,item,e){
    //do somecode

    but after I update the task, the grant autotmaticed scroll to top, how to fix this ?

    • Inga K. April 17, 2014 at 2:36 pm

      Is it possible that in “do somecode” you are modifying the main collection that stores all tasks ?

      When collection is modified, dhtmlxGantt will repaint all events which can cause the scroll state change.

      • Tuan April 21, 2014 at 5:24 am

        No. I just need wrote:
        //nothing here
        But the page also auto scroll to top

  5. dineshujjwal June 14, 2014 at 6:33 am

    hello dear sir can you make date wise calender filter such as when user click on any date than in side panel related to that date all data will be filter …. thanx

    • Ivan (DHTMLX team) June 17, 2014 at 4:45 pm

      There is an API for a client side filtering, which is described here:

      So you’ll need to watch a selected date and redefine filter function accordingly.

      Please post your further technical questions to our free forum.

  6. Yogesh June 16, 2014 at 4:08 pm

    I am getting this error on console :
    TypeError: Cannot read property ‘0’ of undefined
    at Object.scheduler.render_view_data (file:///E:/yogesh/salesforce/Angular.js/Calender/angular-scheduler-demo-master/lib/scheduler/dhtmlxscheduler.js:157:454)
    at Object.scheduler.update_view (file:///E:/yogesh/salesforce/Angular.js/Calender/angular-scheduler-demo-master/lib/scheduler/dhtmlxscheduler.js:110:196)

    Can you please help me ..

    • Stan June 18, 2014 at 1:49 pm

      Be sure that “data” attribute contains a reference to valid data collection ( array of objects ) in the scope. The above error does look similar to the case, when “data” points to not-existing object.

  7. nicolas June 19, 2014 at 2:24 am

    In the init part of the app.scheduler.js file, i’m trying to change the color for my events :
    //init scheduler
    scheduler.config.max_month_events = 5;
    scheduler.init($element[0], $scope.scheduler.mode, $;

    I only have multi day event.

    Any idea why this is not working ?

    • Stan June 19, 2014 at 3:41 pm

      This option will affect only results of showEvent call. It will not change the default color of event bars. You can do it through css. Something like next:

      .dhx_cal_event_line{ background-color: silver; color:white; }

      • nicolas June 20, 2014 at 12:23 am

        it works fine, thanks !
        I just ahve to figured out how to have one different color per event type .

  8. nicolas June 20, 2014 at 4:55 am

    Sorry to bother you with another question, but how can i change the save/delete button of the lightbox ?
    (i need the data to go to a db)

  9. Dhairya July 6, 2014 at 9:22 am

    getting exception at line “scheduler.init($element[0], $scope.scheduler.mode, $;”. Anybody has some idea?

    • Dhairya July 6, 2014 at 9:56 am

      got it! please fix the order of init method FROM
      “scheduler.init($element[0], $scope.scheduler.mode, $;” TO “scheduler.init($element[0], $, $scope.scheduler.mode);”. Also please end properly at line no. 29

      • Stanislav July 14, 2014 at 7:39 pm

        I have fixed the order of parameters, thanks for the remark.
        Which line do mean by line #29 ?

  10. Deepak August 9, 2014 at 8:51 am

    Hi, Nice article, wanted to try bootstrap along with it. will it work?

    • Ivan (DHTMLX team) August 11, 2014 at 1:24 pm

      Yes, it should work. But we recommend you to use the latest version of dhtmlxScheduler (4.1) if you want to use it with bootstrap.

  11. Kurt October 15, 2014 at 3:02 am

    Hi, I am trying to use the scheduler with AngularJS and Firebase. I followed your example and read the comments above. I am getting data back from Firebase but I can’t get it to load into thhe scheduler. Do you have any examples for “real-time” data? Do you think you may have a connector like your Backbone?

    • Kurt October 16, 2014 at 6:22 pm

      Hi, I figured it out.

  12. Scott November 6, 2014 at 12:07 am

    Is it possible to use this example with UI Router? I’ve hooked up a clickEvent to display/edit event details in another route (an input form) which works great. However when I return to the route containing the scheduler it fails to reinitialize due to a pair of exceptions:

    – Cannot read property ‘replace’ of undefined at (

    – Cannot read property ‘rows’ of null at Object.scheduler._pre_render_events (

    Any advice or pointers would be most appreciated

    • Scott November 6, 2014 at 1:00 am

      Apologies for the noise; still needs further testing but it looks like I was able to resolve this by taking a deep clone of window.scheduler on first run and then replacing the original window.scheduler with a deep clone of the uninitialized copy when returning to my route with the scheduler.

  13. Sangram January 7, 2015 at 4:36 pm


    Can we integrate your code with Yeoman ?
    If yes , please let me know how.


    • Stanislav (DHTMLX team) January 9, 2015 at 6:30 pm

      Unfortunately we don’t have any integration for Yeoman

  14. Prachi January 8, 2015 at 12:40 pm

    please send me code of calender using angular JS which contains leavemodel

    • Stanislav (DHTMLX team) January 9, 2015 at 6:29 pm

      What do you mean by “leavemodel” ?

  15. Gaurav Tikekar February 19, 2015 at 8:28 am


    Could anyone please tell how to fix events on a particular time slot in Day Or Week View of calendar.

    I am trying start_date: new Date(2013, 10, 22, 3, 0, 0, 0 ) with an event but not able to see the event at 3 AM on the calendar. I can see it right at the top.

  16. Nikhil Nanjappa March 17, 2015 at 7:25 pm

    Hey its great stuff but just wanted to point out a thing.

    I was playing around with it on my local and while accessing it via Mobile, Its acting weird – It randomly shifts back to a different month on touch.

    Please let me know if its fixed

  17. Thomas April 22, 2015 at 7:26 pm

    The dhxTemplate example doesn’t handle date filters like `date: ‘yyyymmdd’ `

    This code (not fully tested) should work :

    ` return “\”+scheduler.aFilter(‘”+(parts[1].split(“:”)[0]).trim()+”‘)(event.”+(parts[0]).trim()+ (parts[1].indexOf(“:”) > -1 ? “,”+parts[1].split(“:”)[1] : “”) +”)+\””;


  18. Mark May 12, 2015 at 7:55 pm

    Can you please explain in the following line from a directive:
    where does the scheduler object come from?

  19. muthu May 14, 2015 at 2:18 pm

    in that calendar display 2 months view

  20. Mark May 14, 2015 at 6:33 pm

    <in that calendar display 2 months view
    Did not get it. What view?

  21. Esteban Hdz April 4, 2016 at 9:16 pm

    Can I set the bussines begins/ends hour?

  22. Tim Geyssens April 15, 2016 at 12:56 pm

    Thanks for the details, works great :) but have a question how can we hook into the events, for example I want to show a detail page when clicking on the event…

  23. MOhammed August 10, 2016 at 8:50 pm

    after i add reference dhtmlxscheduler_collision.js i cannot add Event to a schedule

    it keep showing these two errors in the console :

    scheduler._get_section_view is not a function dhtmlxscheduler_collision.js:9

    Cannot read property ‘_dhx_changed’ of undefined

  24. kamalkishore September 26, 2016 at 7:59 am

    Can u plz tell me ,in which var all the newly creating events save Bcoz i have to save that in database.

  25. Alwin james October 10, 2016 at 4:08 pm

    hi, in this document ,have getting events using like a method shown below
    $ = [
    { id:1, text:”Task A-12458″,
    start_date: new Date(2013, 09, 30, 9, 0),
    end_date: new Date(2013, 09, 30, 16, 0) },
    { id:2, text:”Task A-83473″,
    start_date: new Date(2013, 09, 28, 9, 0),
    end_date: new Date(2013, 09, 30, 16, 0) }

    but my data populate from the server.that means id,text,start_date and end_date data is coming from server.but i can’t populate this data in my calendar. am using technologies are mvc 5 and angularjs.anyone please help me

Leave a Reply