Overview

  • The new row sorting feature allows sorting the JavaScript Scheduler rows using the specified row field.
  • The sorting icons in the column headers are activated automatically for columns that have the "sort" field set.
  • You can also use the Scheduler API to change the sort order.

This Scheduler can automatically enable sorting support if there are multiple row header columns defined. It builds upon the new Tabular mode which allows specifying the column content using a field/property of the resource object. 

The Tabular mode (see rowHeaderColumnsMode) and the row sorting are supported since version 2019.4.4064.

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.

Scheduler Rows

Let's say we want to display a schedule for multiple storage locations. These locations will be displayed as rows in the Scheduler:

javascript-scheduler-row-sorting-tutorial-locations-rows.png

The rows are defined using resources array:

dp.resources = [
  {id: "R1", name: "Storage Location #1"},
  {id: "R2", name: "Storage Location #2"},
  {id: "R3", name: "Storage Location #3"},
  {id: "R4", name: "Storage Location #4"},
  {id: "R5", name: "Storage Location #5"},
  {id: "R6", name: "Storage Location #6"}
];

The "id" and "name" properties are required. The id specifies a unique value that is used to find matching events/reservations and the name defines the text to be displayed in the row header.

Row Header Columns

Each of the location has additional properties (capacity, distance) which we want to display in the Scheduler as well.

javascript-scheduler-row-sorting-tutorial-columns.png

We will define the columns using rowHeaderColumns property:

var dp = new DayPilot.Scheduler("dp", {
  rowHeaderColumns: [
    { name: "Name"},
    { name: "Capacity"},
    { name: "Distance"}
  ],
  // ...
});

Extended Row Data

javascript-scheduler-row-sorting-tutorial-row-data.png

In order to display the data for the additional columns we need to add them to the resources array. Note that these properties are not predefined. You can use any name that doesn't have a special meaning (see resources). We will use "capacity" and "distance":

dp.resources = [
  {id: "R1", name: "Storage Location #1", capacity: 40, distance: 100},
  {id: "R2", name: "Storage Location #2", capacity: 15, distance: 20},
  {id: "R3", name: "Storage Location #3", capacity: 5, distance: 20},
  {id: "R4", name: "Storage Location #4", capacity: 20, distance: 100},
  {id: "R5", name: "Storage Location #5", capacity: 20, distance: 200},
  {id: "R6", name: "Storage Location #6", capacity: 25, distance: 300}
];

And we tell the Scheduler to load the data from these properties using display property of the rowHeaderColumns items:

var dp = new DayPilot.Scheduler("dp", {
    rowHeaderColumns: [
      { name: "Name", display: "name"},
      { name: "Capacity", display: "capacity"},
      { name: "Distance", display: "distance"}
    ],
  // ...
});

You can see that we have used our new properties ("capacity", "distance") but also the predefined "name" property - both will work fine.

Automatic Row Sorting

javascript-scheduler-row-sorting-tutorial-icons.png

In order to activate the built-in row sorting support, we just need to define the field that will be used for each column using sort property or the rowHeaderColumns array:

var dp = new DayPilot.Scheduler("dp", {
  rowHeaderColumns: [
    { name: "Name", width: 150, display: "name", sort: "name"},
    { name: "Capacity", display: "capacity", sort: "capacity"},
    { name: "Distance", display: "distance", sort: "distance"}
  ],
  // ...
});

Sorting using Scheduler API

javascript-scheduler-row-sorting-tutorial-api.png

You can also sort the Scheduler row manually using rows.sort() method. The row.sort() method accepts an object with the following structure:

{
  field: "capacity",
  order: "asc"
}

We will add three buttons that will sort the rows using the specified rule:

HTML

<button class="sort-button" data-field="name">Name</button>
<button class="sort-button" data-field="capacity">Capacity</button>
<button class="sort-button" data-field="distance" data-direction="desc">Distance (Desc)</button>

JavaScript

var buttons = document.getElementsByClassName("sort-button");
[].forEach.call(buttons, function(button) {
  button.addEventListener("click", function(ev) {
    var sorting = {
      field: button.dataset.field,
      order: button.dataset.order || "asc"
    };
    dp.rows.sort(sorting);
  });
});

Full Source Code

And here is the full source code of our Scheduler view with row sorting support:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8"/>
  <title>JavaScript Scheduler: Row Sorting Tutorial</title>

  <style type="text/css">
    /* ... */
  </style>

  <!-- DayPilot library -->
  <script src="js/daypilot/daypilot-all.min.js"></script>
</head>
<body>
<div class="header">
  <h1><a href='https://code.daypilot.org/78411/javascript-scheduler-row-sorting-tutorial'>JavaScript Scheduler: Row Sorting Tutorial</a></h1>
  <div><a href="https://javascript.daypilot.org/">DayPilot for JavaScript</a> - HTML5 Calendar/Scheduling Components for JavaScript/Angular/React/Vue</div>
</div>


<div class="main">
  <div class="space">
    Sort using API:
    <button class="sort-button" data-field="name">Name</button>
    <button class="sort-button" data-field="capacity">Capacity</button>
    <button class="sort-button" data-field="distance" data-direction="desc">Distance (Desc)</button>
  </div>
  <div id="dp"></div>
  <div class="generated">Generated using <a href="https://builder.daypilot.org/">DayPilot UI Builder</a>.</div>
</div>

<script>
  var dp = new DayPilot.Scheduler("dp", {
    timeHeaders: [{"groupBy":"Month"},{"groupBy":"Day","format":"d"}],
    scale: "Day",
    days: DayPilot.Date.today().daysInMonth(),
    startDate: DayPilot.Date.today().firstDayOfMonth(),
    rowHeaderColumns: [
      { name: "Name", width: 150, display: "name", sort: "name"},
      { name: "Capacity", display: "capacity", sort: "capacity"},
      { name: "Distance", display: "distance", sort: "distance"}
    ],
    onTimeRangeSelected: function (args) {
      var dp = this;
      DayPilot.Modal.prompt("Create a new event:", "Event 1").then(function(modal) {
        dp.clearSelection();
        if (!modal.result) { return; }
        dp.events.add(new DayPilot.Event({
          start: args.start,
          end: args.end,
          id: DayPilot.guid(),
          resource: args.resource,
          text: modal.result
        }));
      });
    },
  });
  dp.resources = [
    {id: "R1", name: "Storage Location #1", capacity: 40, distance: 100},
    {id: "R2", name: "Storage Location #2", capacity: 15, distance: 20},
    {id: "R3", name: "Storage Location #3", capacity: 5, distance: 20},
    {id: "R4", name: "Storage Location #4", capacity: 20, distance: 100},
    {id: "R5", name: "Storage Location #5", capacity: 20, distance: 200},
    {id: "R6", name: "Storage Location #6", capacity: 25, distance: 300}
  ];
  dp.events.list = [];
  dp.init();
</script>

<script>
  var buttons = document.getElementsByClassName("sort-button");
  [].forEach.call(buttons, function(button) {
    button.addEventListener("click", function(ev) {
      var sorting = {
        field: button.dataset.field,
        order: button.dataset.order || "asc"
      };
      dp.rows.sort(sorting);
    });
  });
</script>

</body>
</html>