Features

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.

Event Context Menu

angular scheduler dynamic context menu enabled

The event context menu is defined using contextMenu property of the config object.

config: DayPilot.SchedulerConfig = {
  contextMenu: new DayPilot.Menu({
    items: [
      { text: "Delete", onClick: (args) => { this.scheduler.control.events.remove(args.source); } },
      { text: "-"},
      {
        text: "Blue",
        icon: "icon icon-blue",
        tags: { color: "#1155cc" },
        onClick: args => { this.updateColor(args.source, args.item.tags.color); }
      },
      {
        text: "Green",
        icon: "icon icon-green",
        tags: { color: "#6aa84f" },
        onClick: args => { this.updateColor(args.source, args.item.tags.color); }
      },
      {
        text: "Yellow",
        icon: "icon icon-yellow",
        tags: { color: "#f1c232" },
        onClick: args => { this.updateColor(args.source, args.item.tags.color); }
      },
      {
        text: "Red",
        icon: "icon icon-red",
        tags: { color: "#cc0000" },
        onClick: args => { this.updateColor(args.source, args.item.tags.color); }
      },
    ],
    onShow: args => {
      let e = args.source;

      // disable deleting for events that start in the past
      if (e.start() < DayPilot.Date.today()) {
        args.menu.items[0].disabled = true;
      }
      else {
        args.menu.items[0].disabled = false;
      }
    }
  }),

  // ...

};

The updateColor method changes the bar color of the selected Scheduler event:

updateColor(e: DayPilot.Event, color: string): void {
  e.data.barColor = color;
  this.scheduler.control.events.update(e);
}

Dynamic Modification of the Event Context Menu

angular scheduler dynamic context menu disabled

You can modify the context menu properties upon invocation by handling the onShow event handler.

This event handler checks the event start date. If the event starts before today, the first menu item ("Delete" action) is disabled.

config: DayPilot.SchedulerConfig = {
  contextMenu: new DayPilot.Menu({
    items: [
      { text: "Delete", onClick: (args) => { this.scheduler.control.events.remove(args.source); } },
      // ...
    ],
    onShow: args => {
      let e = args.source;

      // disable deleting for events that start in the past
      if (e.start() < DayPilot.Date.today()) {
        args.menu.items[0].disabled = true;
      }
      else {
        args.menu.items[0].disabled = false;
      }
    }
  }),
  // ...
}

Dynamic Row Header Context Menu

The same method can be used to customize the row header context menu depending on the row. This example displays a different menu for resource groups and resources.

Context menu for parent rows (groups):

angular scheduler dynamic context menu group

Context menu for resources (rows without children):

angular scheduler dynamic context menu resource

In this example, we have defined two different menu item arrays. We use the onShow event handler to set the items property as needed.

config: DayPilot.SchedulerConfig = {
  contextMenuResource: new DayPilot.Menu({
    onShow: args => {
      let hasChildren = args.source.children().length > 0;
      if (hasChildren) {
        args.menu.items = this.menuItemsGroup;
      }
      else {
        args.menu.items = this.menuItemsResource;
      }
    }
  })
}

menuItemsGroup: any[] = [
  { text: "Group Details"}
];

menuItemsResource: any[] = [
  { text: "Resource Details"}
];

Source Code

Here is the full source code of the customized Angular Scheduler component that uses dynamically-modified context menus.

scheduler.component.ts

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

@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":"d"}],
    scale: "Day",
    days: 31,
    startDate: "2021-07-01",
    treeEnabled: true,
    separators: [
      {color: "red", location: DayPilot.Date.today() }
    ],
    onTimeRangeSelected: async (args) => {
      const dp = args.control;
      const modal = await DayPilot.Modal.prompt("Create a new event:", "Event 1");
      dp.clearSelection();
      if (!modal.result) { return; }
      dp.events.add({
        start: args.start,
        end: args.end,
        id: DayPilot.guid(),
        resource: args.resource,
        text: modal.result
      });

    },
    contextMenu: new DayPilot.Menu({
      items: [
        { text: "Delete", onClick: (args) => { this.scheduler.control.events.remove(args.source); } },
        { text: "-"},
        {
          text: "Blue",
          icon: "icon icon-blue",
          tags: { color: "#1155cc" },
          onClick: args => { this.updateColor(args.source, args.item.tags.color); }
        },
        {
          text: "Green",
          icon: "icon icon-green",
          tags: { color: "#6aa84f" },
          onClick: args => { this.updateColor(args.source, args.item.tags.color); }
        },
        {
          text: "Yellow",
          icon: "icon icon-yellow",
          tags: { color: "#f1c232" },
          onClick: args => { this.updateColor(args.source, args.item.tags.color); }
        },
        {
          text: "Red",
          icon: "icon icon-red",
          tags: { color: "#cc0000" },
          onClick: args => { this.updateColor(args.source, args.item.tags.color); }
        },
      ],
      onShow: args => {
        let e = args.source;

        // disable deleting for events that start in the past
        if (e.start() < DayPilot.Date.today()) {
          args.menu.items[0].disabled = true;
        }
        else {
          args.menu.items[0].disabled = false;
        }
      }
    }),
    contextMenuResource: new DayPilot.Menu({
      onShow: args => {
        let hasChildren = args.source.children().length > 0;
        if (hasChildren) {
          args.menu.items = this.menuItemsGroup;
        }
        else {
          args.menu.items = this.menuItemsResource;
        }
      }
    })
  };

  menuItemsGroup: any[] = [
    { text: "Group Details"}
  ];

  menuItemsResource: any[] = [
    { text: "Resource Details"}
  ];

  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;
    });
  }

  updateColor(e: DayPilot.Event, color: string): void {
    e.data.barColor = color;
    this.scheduler.control.events.update(e);
  }

}