• The resource calendar component displays custom columns instead of days.

  • You can specify custom width of each column.

  • You can enable column resizing - users will be able to change the column using drag and drop.

  • You can let users change the order of columns using drag and drop (enable column moving).

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


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.

Custom Column Widths

javascript resource calendar custom column widths

In the resource calendar mode, the calendar component lets you specify custom width of the columns that display resources.

  • It works in the default auto column width mode which sets the column width automatically to fill the calendar width.

  • It also works in the fixed column width mode which sets the width of columns in pixels (and adds a horizontal scrollbar if needed).

The following example shows how to set custom width for selected calendar columns:

  const calendar = new DayPilot.Calendar("calendar", {
    viewType: "Resources",
    columnWidthSpec: "Auto",
    // ...
  calendar.columns.list = [
    {name: "Resource 1", id: "R1", width: 20},
    {name: "Resource 2", id: "R2", width: 5},
    {name: "Resource 3", id: "R3", width: 5},
    {name: "Resource 4", id: "R4"},
    {name: "Resource 5", id: "R5"},
    {name: "Resource 6", id: "R6"},
    {name: "Resource 7", id: "R7"},
    {name: "Resource 8", id: "R8"},
    {name: "Resource 9", id: "R9"},
    {name: "Resource 10", id: "R10"},
    {name: "Resource 11", id: "R11"},
    {name: "Resource 12", id: "R12"},

The Percentage Widths are Rebalanced Automatically

In the auto column width mode, the calendar column width is specified using percentage values. The total of all widths may not always make 100% and in such cases the widths will be rebalanced automatically. This means you can see different width values for columns that were not resized at all.

You can prevent the rebalancing if you specify the width for all columns explicitly and make sure the total makes 100


  • The resource calendar displays 10 resources.

  • The default width of columns with no width specified is calculated as 10% (= 100/10).

  • If you specify 20 as a width of the first column, the total of the percentages is over 100. In this case, the widths of all columns will be reduced proportionally.

  • The total of all width values is 110 (= 20 + 9 * 10)

  • The calendar will use a ratio of 1.1 to reduce all width values (= 110 / 100)

  • The widths will be rebalanced as follows: the width of the first column will be 18.18 (= 20 / 1.1), the width of the remaining columns will be 9.09 (= 10 / 1.1)

  • After rebalancing, the total width is 100 again (= 18.18 + 9 * 9.09)

How to Enable Column Resizing

javascript resource calendar drag and drop column resizing

You can enable calendar column resizing using columnResizeHandling property. By default, column resizing is disabled (the value is set to "Disabled"). To enable it, set the value to "Update".

const calendar = new DayPilot.Calendar("calendar", {
  // ...
  columnResizedHandling: "Update",
  // ...

The resource calendar will show a splitter at the right side of each column header on hover. You can drag the splitter to change the calendar column width.

How to Save the New Column Widths to Database

There are two event handlers that will be fired when you finish the resizing:

If you want to read the new values, use onColumnResized. When this event is called, the values in columns.list are already updated. You can save the new values to the database so they can be loaded the next time.

These event handlers provide access to the column that was resized (args.column) and the new width (args.newWidth) but remember that in the auto cell width mode, it will not be the only column that is updated. All columns on the right will updated as well so that the total of all widths make 100. To save the new column layout, you will have to store the new width values of all columns.

How to Cancel the Resizing and Reset the Original Layout

The onColumnResize event is fired before the values in columns.list are updated and you can cancel the resizing operation here using args.preventDefault().

onColumnResize: args => {

This will reset the original state before the drag and drop resizing was started.

How to Enforce a Minimum Column Width

javascript resource calendar minimum column width

Use the columnWidthMin property to set the minimum column width. The minimum width is always specified in pixels. The pixel value will be enforced in auto cell width mode as well (which otherwise uses percentage values).

How to Enable Column Reordering

javascript resource calendar column reordering

You can enable column reordering using the columnMoveHandling property. The default value is "Disabled" - in order to enable drag and drop column moving, set the value to "Update".

const calendar = new DayPilot.Calendar("calendar", {
  // ...
  columnMoveHandling: "Update",
  // ...

This feature works for the column hierarchy as well. When the hierarchy is enabled, you can move a column to become a child of another column.

In this example, we display a flat structure (columns don’t have children). In order to keep the structure flat, we need to add columnMoveSameLevelOnly: true to the calendar config. This way you can only move columns next to an existing column, not to become its child. During drag and drop, the calendar will only offer "before" and "after" target positions.

How to Enforce Custom Rules during Column Moving

javascript resource calendar cusotm column reordering rules

During the drag and drop moving, the calendar fires a real-time onColumnMoving event. This event is fired whenever the target position changes. You can read the current position using args.target and args.position properties. The column that is being moved is accessible as args.source.

You can use this event to display additional information during the operation.

You can also forbid the target position if it doesn’t meet custom rules. It lets you implement rules such as:

  • Certain column can’t be moved at all.

  • Two specific columns can’t be next to each other.

  • A column can’t be moved to become a child of another column.

  • A specified target can’t have any children.

  • The first or last column must remain in place (they can’t be moved and any other column can’t be moved to this position).


onColumnMoving: args => {
  const firstId = "R1";

  if (args.source.id === firstId) {
    args.position = "forbidden";
  else if (args.target.id === firstId && args.position === "before") {
    args.position = "forbidden";

This first condition disables moving of the first column:

  if (args.source.id === firstId) {
    args.position = "forbidden";

The second condition disables moving other columns before the first one:

  else if (args.target.id === firstId && args.position === "before") {
    args.position = "forbidden";