Overview

  • A project that uses Angular Scheduler component to manage reservations for tables.

  • Use the project as a starting point for your own Angular scheduling application.

  • The tutorial describes the basic steps required to add the Scheduler component to your application.

  • Includes a trial version of DayPilot Pro for JavaScript (see License below)

New Version

There is a new version of this Angular project available:

License

Licensed for testing and evaluation purposes. Please see the license agreement included in the sample project. You can use the source code of the tutorial if you are a licensed user of DayPilot Pro for JavaScript.

Angular 11 Scheduler Component

The Angular 11 Scheduler component is included in daypilot-pro-angular package. You can install it from npm.daypilot.org:

npm install https://npm.daypilot.org/daypilot-pro-angular/trial/2020.4.4788.tar.gz --save

The scheduling components are available in DayPilotModule. In order to use the Scheduler component, it is necessary to import the module:

@NgModule({
  imports:      [
    // ...
    DayPilotModule
  ],
  // ...
})
export class SchedulerModule { }

As soon as the DayPilotModule is imported, you can add <daypilot-scheduler> tag to the component HTML template:

@Component({
  selector: 'scheduler-component',
  template: `
    <daypilot-scheduler [config]="config" [events]="events" #scheduler></daypilot-scheduler>`,
  styles: [``]
})
export class SchedulerComponent implements AfterViewInit {
  // ...
}

You can see that the <daypilot-scheduler> tag defines two attributes: [config] and [events].

The [config] attribute points to a configuration object which defines the Angular scheduler properties:

export class SchedulerComponent implements AfterViewInit {

  config: DayPilot.SchedulerConfig = {
    timeHeaders: [{groupBy: 'Month'}, {groupBy: 'Day', format: 'dddd MMMM d, yyyy'}, {groupBy: 'Hour'}],
    scale: 'Hour',
    cellWidth: 80,
    days: 31,
    startDate: '2020-12-01',
    treeEnabled: true,
    // ...
  };

}

The configuration properties lets you define the Scheduler appearance and behavior. You can use them to enable or configure the Scheduler features as described in the Scheduler component documentation. You can find the complete list of properties and events in the API documentation.

You can also test selected configuration option in the online UI Builder application that lets you configure the Scheduler and preview the changes immediately. The UI Builder lets you download a complete Angular project with your selected configuration. You can use the downloaded project to build your own application.

The [events] object defines the events/reservations to be displayed in the main Scheduler grid:

export class SchedulerComponent implements AfterViewInit {

  events: DayPilot.EventData[] = [];

  // ...

}

You can load the event data using DataService class in ngAfterViewInit():

export class SchedulerComponent implements AfterViewInit {

  events: DayPilot.EventData[] = [];

  constructor(private ds: DataService) {
  }

  ngAfterViewInit(): void {
  
    // ...
  
    const from = this.scheduler.control.visibleStart();
    const to = this.scheduler.control.visibleEnd();
    this.ds.getEvents(from, to).subscribe(result => {
      this.events = result;
    });
  }

}

In this example, the DataService.getEvents() method returns a static set of events. In a standard application, you’d load the data from an HTTP/REST API instead:

import {Injectable} from '@angular/core';
import {DayPilot} from 'daypilot-pro-angular';
import {HttpClient} from '@angular/common/http';
import {Observable} from 'rxjs';

@Injectable()
export class DataService {

  events: DayPilot.EventData[] = [
    {
      id: '1',
      resource: 'T1',
      start: '2020-12-03T12:00:00',
      end: '2020-12-03T15:00:00',
      text: 'Reservation 1',
      tags: {
        color: '#e69138'
      }
    },
    // ...
  ];

  constructor(private http: HttpClient) {
  }

  getEvents(from: DayPilot.Date, to: DayPilot.Date): Observable<any[]> {

    // simulating an HTTP request
    return new Observable(observer => {
      setTimeout(() => {
        observer.next(this.events);
      }, 200);
    });

    // return this.http.get("/api/events?from=" + from.toString() + "&to=" + to.toString());
  }

  // ...

}

Full Source Code

scheduler.component.ts

import {AfterViewInit, Component, ViewChild} from '@angular/core';
import {DayPilot, DayPilotSchedulerComponent} from 'daypilot-pro-angular';
import {DataService} from './data.service';
import ModalClosedArgs = DayPilot.ModalClosedArgs;

@Component({
  selector: 'scheduler-component',
  template: `
    <daypilot-scheduler [config]="config" [events]="events" #scheduler></daypilot-scheduler>`,
  styles: [``]
})
export class SchedulerComponent implements AfterViewInit {

  @ViewChild('scheduler')
  scheduler: DayPilotSchedulerComponent;

  events: DayPilot.EventData[] = [];

  config: DayPilot.SchedulerConfig = {
    timeHeaders: [{groupBy: 'Month'}, {groupBy: 'Day', format: 'dddd MMMM d, yyyy'}, {groupBy: 'Hour'}],
    scale: 'Hour',
    cellWidth: 80,
    days: 31,
    startDate: '2020-12-01',
    timeRangeSelectedHandling: 'Enabled',
    onTimeRangeSelected: (args: DayPilot.SchedulerTimeRangeSelectedArgs) => {
      const dp = this.scheduler.control;
      DayPilot.Modal.prompt('Create a new event:', 'Event 1').then((modal: ModalClosedArgs) => {
        dp.clearSelection();
        if (modal.canceled) {
          return;
        }
        dp.events.add({
          start: args.start,
          end: args.end,
          id: DayPilot.guid(),
          resource: args.resource,
          text: modal.result
        });
      });
    },
    onEventMoved: (args: DayPilot.SchedulerEventMovedArgs) => {
      this.scheduler.control.message('Event moved: ' + args.e.text());
    },
    onEventResized: (args: DayPilot.SchedulerEventResizedArgs) => {
      this.scheduler.control.message('Event resized: ' + args.e.text());
    },
    eventDeleteHandling: 'Update',
    onEventDeleted: (args: DayPilot.SchedulerEventDeletedArgs) => {
      this.scheduler.control.message('Event deleted: ' + args.e.text());
    },
    onBeforeEventRender: (args: DayPilot.SchedulerBeforeEventRenderArgs) => {
      args.data.backColor = (args.data.tags && args.data.tags.color) || '#dddddd';
      args.data.borderColor = 'darker';
      args.data.barHidden = true;
      args.data.fontColor = 'white';
    },
    treeEnabled: true,
  };

  constructor(private ds: DataService) {
  }

  ngAfterViewInit(): void {
    this.ds.getResources().subscribe(result => this.config.resources = result);

    const from = this.scheduler.control.visibleStart();
    const to = this.scheduler.control.visibleEnd();
    this.ds.getEvents(from, to).subscribe(result => {
      this.events = result;
    });

    this.scheduler.control.scrollTo('2020-12-03T09:00:00');
  }

}

data.service.json

import {Injectable} from '@angular/core';
import {DayPilot} from 'daypilot-pro-angular';
import {HttpClient} from '@angular/common/http';
import {Observable} from 'rxjs';

@Injectable()
export class DataService {

  resources: DayPilot.ResourceData[] = [
    {
      name: 'Section A', id: 'GA', expanded: true, children: [
        {name: 'Table 1', id: 'T1'},
        {name: 'Table 2', id: 'T2'},
        {name: 'Table 3', id: 'T3'},
        {name: 'Table 4', id: 'T4'},
        {name: 'Table 5', id: 'T5'},
        {name: 'Table 6', id: 'T6'},
      ]
    },
    {
      name: 'Section B', id: 'GB', expanded: true, children: [
        {name: 'Table 7', id: 'T7'},
        {name: 'Table 8', id: 'T8'},
        {name: 'Table 9', id: 'T9'},
        {name: 'Table 10', id: 'T10'},
        {name: 'Table 11', id: 'T11'},
      ]
    }
  ];

  events: DayPilot.EventData[] = [
    {
      id: '1',
      resource: 'T1',
      start: '2020-12-03T12:00:00',
      end: '2020-12-03T15:00:00',
      text: 'Reservation 1',
      tags: {
        color: '#e69138'
      }
    },
    {
      id: '2',
      resource: 'T3',
      start: '2020-12-03T11:00:00',
      end: '2020-12-03T14:00:00',
      text: 'Reservation 2',
      tags: {
        color: '#6aa84f'
      }
    },
    {
      id: '3',
      resource: 'T5',
      start: '2020-12-03T12:00:00',
      end: '2020-12-03T14:00:00',
      text: 'Reservation 3',
      tags: {
        color: '#3c78d8'
      }
    }
  ];

  constructor(private http: HttpClient) {
  }

  getEvents(from: DayPilot.Date, to: DayPilot.Date): Observable<any[]> {

    // simulating an HTTP request
    return new Observable(observer => {
      setTimeout(() => {
        observer.next(this.events);
      }, 200);
    });

    // return this.http.get("/api/events?from=" + from.toString() + "&to=" + to.toString());
  }

  getResources(): Observable<any[]> {

    // simulating an HTTP request
    return new Observable(observer => {
      setTimeout(() => {
        observer.next(this.resources);
      }, 200);
    });

    // return this.http.get("/api/resources");
  }

}

scheduler.module.ts

import {DataService} from './data.service';
import {FormsModule} from '@angular/forms';
import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {SchedulerComponent} from './scheduler.component';
import {DayPilotModule} from 'daypilot-pro-angular';
import {HttpClientModule} from '@angular/common/http';

@NgModule({
  imports:      [
    BrowserModule,
    FormsModule,
    HttpClientModule,
    DayPilotModule
  ],
  declarations: [
    SchedulerComponent
  ],
  exports:      [ SchedulerComponent ],
  providers:    [ DataService ]
})
export class SchedulerModule { }

package.json

{
  "name": "angular11-scheduler",
  "license": "SEE LICENSE IN license/LicenseAgreementTrial.pdf",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~11.0.0",
    "@angular/common": "~11.0.0",
    "@angular/compiler": "~11.0.0",
    "@angular/core": "~11.0.0",
    "@angular/forms": "~11.0.0",
    "@angular/platform-browser": "~11.0.0",
    "@angular/platform-browser-dynamic": "~11.0.0",
    "@angular/router": "~11.0.0",
    "daypilot-pro-angular": "https://npm.daypilot.org/daypilot-pro-angular/trial/2020.4.4788.tar.gz",
    "rxjs": "~6.6.0",
    "tslib": "^2.0.0",
    "zone.js": "~0.10.2"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.1100.0",
    "@angular/cli": "~11.0.0",
    "@angular/compiler-cli": "~11.0.0",
    "@types/jasmine": "~3.6.0",
    "@types/node": "^12.11.1",
    "codelyzer": "^6.0.0",
    "jasmine-core": "~3.6.0",
    "jasmine-spec-reporter": "~5.0.0",
    "karma": "~5.1.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.0.3",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "protractor": "~7.0.0",
    "ts-node": "~8.3.0",
    "tslint": "~6.1.0",
    "typescript": "~4.0.2"
  }
}