Overview

  • The Angular Scheduler component can display frozen rows at the top and/or bottom of the grid.

  • You can use the dynamic content generation events to calculate the resource utilization and display the percentage and a bar chart in the summary row cells.

  • This tutorial covers advanced configuration options and assumes you are already familiar with the component. For an introduction to using the Angular Scheduler component, please see the Angular Scheduler Tutorial.

  • The project includes a trial version of DayPilot Pro for JavaScript (see License below)

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. Buy a license.

How to add fixed rows to the top of the Angular Scheduler?

angular scheduler resource utilization workload chart rows

We will use the frozen rows feature to display fixed rows at the top of the Angular Scheduler component. The frozen (sticky) rows are displayed at a fixed position and they remain visible even when the users scroll the Scheduler grid. The frozen rows can be displayed at the top and/or at the bottom of the Scheduler.

Our Angular Scheduler will display two frozen rows at the top:

  • The “Workload” row will display the utilization of the available resources as percentage.

  • The “Chart” row will display bars that represent the utilization graphically.

To display the frozen rows, we extend the resources array with summary rows and fix them at the top of the Angular Scheduler using frozen: "top" property.

Note that we also disable the drag and drop for these rows by adding cellDisabled: true to the properties. This will ensure that users won’t be able to create events in the summary rows.

ngAfterViewInit(): void {
  this.ds.getResources().subscribe(result => {
    this.config.resources = [
      {name: "Workload", id: "workload", frozen: "top", cellsAutoUpdated: true, cellsDisabled: true},
      {name: "Chart", id: "chart", frozen: "top", cellsAutoUpdated: true, cellsDisabled: true},
      ...result
    ];
  });


  // ...
}

How to display workload percentage for the time slots?

angular scheduler resource utilization workload percentage

The “Workload” row displays the percentage of resources occupied by events, tasks or reservations.

You can set the content of the frozen row cells using onBeforeCellRender event handler. We will use the event handler to calculate the percentage value from the time slots below the summary cell.

Note that we have marked the cells for auto update by adding cellsAutoUpdated property to the summary rows in the resources[] array. This will ensure that the content of the cells in the summary rows is updated on every data change. If you don’t don’t enable the auto update, the result of onBeforeCellRender event handler will be cached and reused to improve performance.

First, we find the rows that are available for scheduling. The rows.all() method of the Scheduler returns all rows as an array of DayPilot.Row objects. We need to filter out rows that are not used for scheduling:

  • the frozen rows which are used for displaying the availability (r.data.frozen)

  • parent rows (r.children().length > 0).

const resources = scheduler.rows.all().filter(r => !r.data.frozen && !r.children().length);

Now we need to find the events for the specified time slot:

const events = scheduler.events.forRange(args.cell.start, args.cell.end);

The workload percentage is calculated from the fraction of the scheduled events and the available resources:

const percentage = 100.0 * events.length / max;

Now we can display the percentage in the header cell. We will use an active area so we can center the content vertically and horizontally:

args.cell.properties.areas = [
  {left:0, top: 0, right: 0, bottom: 0, style: "display: flex; justify-content: center; align-items: center;", text: `${percentage}%` },
];

Here is the full onBeforeCellRender code that displays the utilization percentage:

config: DayPilot.SchedulerConfig = {

  onBeforeCellRender: args => {
    const scheduler = this.scheduler.control;
    const resources = scheduler.rows.all().filter(r => !r.data.frozen && !r.children().length);
    const max = resources.length;
    const events = scheduler.events.forRange(args.cell.start, args.cell.end).length;
    const utilization = events / max;

    if (args.cell.resource === "workload") {

      const percentage = 100 * utilization;

      args.cell.properties.backColor = "#ffffff";
      args.cell.properties.areas = [
        {left:0, top: 0, right: 0, bottom: 0, style: "display: flex; justify-content: center; align-items: center;", text: `${percentage}%` },
      ];
    }
  },
  
  // ...
  
}

How to display resource utilization bar chart in the Angular Scheduler?

angular scheduler resource utilization bar chart

The “Chart” row displays a bar chart that shows the resource utilization graphically.

We already have the utilization value pre-calculated so we can use it to set the height of a custom active area:

  • The height of the active area is set according to the utilization percentage (100% == the row height).

  • The opacity of the active area increases with the utilization percentage.

config: DayPilot.SchedulerConfig = {

  onBeforeCellRender: args => {
    const scheduler = this.scheduler.control;
    const resources = scheduler.rows.all().filter(r => !r.data.frozen && !r.children().length);
    const max = resources.length;
    const events = scheduler.events.forRange(args.cell.start, args.cell.end).length;
    const utilization = events / max;

    if (args.cell.resource === "chart") {
      args.cell.properties.backColor = "#ffffff";
      if (events > 0) {

        const maxHeight = scheduler.eventHeight || 30;
        const percentage = Math.min(utilization, 1);
        const height = percentage * maxHeight;

        args.cell.properties.areas = [
          {
            bottom: 0,
            height: height,
            left: 0,
            right: 0,
            backColor: "#f6b26b",
            style: "box-sizing: border-box; border: 1px solid #e69138; opacity: " + percentage
          }
        ];
      }

    }
  },
  
  // ...
  
}