Overview

  • Hide the built-in sort icon for selected columns, but keep the column sortable using the API.
  • Use custom sort icons from Font Awesome.
  • Customize the sort icon behavior.
  • 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.

Live Demo

Row Sorting Cofiguration

javascript-scheduler-row-sorting-configuration.png

We are going to display two columns in the row header of the JavaScript Scheduler component:

  • Name
  • Capacity

The columns are defined using rowHeaderColumns property. The array items specify the column title (name), column content field name (display) and field used for sorting (sort).

This enables row sorting using the built-in sort icons.

dp.resources = [
  {name: "Resource 1", id: "R1", capacity: 10},
  {name: "Resource 2", id: "R2", capacity: 5},
  {name: "Resource 3", id: "R3", capacity: 15},
  {name: "Resource 4", id: "R4", capacity: 20},
  {name: "Resource 5", id: "R5", capacity: 10},
  {name: "Resource 6", id: "R6", capacity: 30},
  {name: "Resource 7", id: "R7", capacity: 10},
  {name: "Resource 8", id: "R8", capacity: 20},
  {name: "Resource 9", id: "R9", capacity: 15},
];

dp.rowHeaderColumns = [
  {name: "Name", display: "name", sort: "name", width: 100},
  {name: "Capacity", display: "capacity", sort: "capacity"},
];

Hiding the Sort Icon

javascript-scheduler-row-sorting-capacity-column-disabled.png

It is possible to hide the built-in sort icon for specified columns using onBeforeRowHeaderColumnRender event handler.

The following example hides the sort icon for the "Capacity" column:

dp.onBeforeRowHeaderColumnRender = function(args) {
  if (args.column.data.name === "Capacity") {
    args.column.sortingEnabled = false;
  }
};

The demo project uses a checkbox which lets you change the sort icon visibility on the fly:

HTML

<label><input type="checkbox" id="allowCapacity" checked>Allow sorting by "Capacity"</label>
<div id="dp"></div>

JavaScript

var elements = {
  allowCapacity: document.getElementById("allowCapacity"),
  customIcons: document.getElementById("customIcons"),
};

elements.allowCapacity.addEventListener("click", function() {
  dp.update();
});

// ...

dp.onBeforeRowHeaderColumnRender = function(args) {
  if (args.column.data.name === "Capacity") {
    args.column.sortingEnabled = !elements.disableCapacity.checked;
  }
};

Custom Icons and Sort Logic

javascript-scheduler-row-sorting-custom-sort-icons.png

You can also use the onBeforeRowHeaderColumnRender event handler to display a custom sort icon.

First, it is necessary to hide the default sort icon:

dp.onBeforeRowHeaderColumnRender = function(args) {
  args.column.sortingEnabled = false;
  // ...
};

Now you can define your own icons using active areas. The active areas support font icons using icon property so we can use a sorting icon from Font Awesome easily (fa-sort).

dp.onBeforeRowHeaderColumnRender = function(args) {
  var useCustomIcons = elements.customIcons.checked;
  if (useCustomIcons) {
    args.column.sortingEnabled = false;
    args.column.areas = [
      {
        right: 4,
        top: 10,
        height: 17,
        width: 10,
        icon: "fa fa-sort",
        style: "cursor: pointer",
        onClick: function() {
          dp.rows.sort({
            field: args.column.data.sort,
            order: (dp.rows.sortParam.field === args.column.data.sort && dp.rows.sortParam.order === "asc") ? "desc": "asc"
          });
        }
      }
    ];
  }
};

Full Source Code

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>JavaScript Scheduler: Row Sorting Customization</title>

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

  <style>
    input[type=checkbox], input[type=radio] {
      vertical-align: middle;
      position: relative;
      bottom: .08em;
    }
  </style>

  <!-- DayPilot library -->
  <script src="js/daypilot/daypilot-all.min.js"></script>

  <!-- font awesome -->
  <link type="text/css" rel="stylesheet" href="fa-5.9.0/css/all.min.css" />

</head>
<body>
<div class="header">
  <h1><a href='https://code.daypilot.org/43915/javascript-scheduler-row-sorting-customization'>JavaScript Scheduler: Row Sorting Customization</a></h1>
  <div><a href="https://javascript.daypilot.org/">DayPilot for JavaScript</a> - HTML5 Calendar/Scheduling Components for JavaScript/Angular/React</div>
</div>

<div class="main">
  <div class="space">
    <label><input type="checkbox" id="disableCapacity">Disable sorting by "Capacity"</label>
    <label><input type="checkbox" id="customIcons" >Use custom icons</label>
  </div>
  <div id="dp"></div>
  <div class="generated">Generated using <a href="https://builder.daypilot.org/">DayPilot UI Builder</a>.</div>
</div>


<script>
  var elements = {
    disableCapacity: document.getElementById("disableCapacity"),
    customIcons: document.getElementById("customIcons"),
  };

  elements.disableCapacity.addEventListener("click", function() {
    dp.update();
  });

  elements.customIcons.addEventListener("click", function() {
    var  useCustomIcons = elements.customIcons.checked;

    elements.disableCapacity.disabled = useCustomIcons;
    if (useCustomIcons) {
      elements.disableCapacity.checked = false;
    }

    dp.update();
  });

</script>


<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(),
    timeRangeSelectedHandling: "Enabled",
    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
        }));
      });
    },
    treeEnabled: true,
  });
  dp.resources = [
    {name: "Resource 1", id: "R1", capacity: 10},
    {name: "Resource 2", id: "R2", capacity: 5},
    {name: "Resource 3", id: "R3", capacity: 15},
    {name: "Resource 4", id: "R4", capacity: 20},
    {name: "Resource 5", id: "R5", capacity: 10},
    {name: "Resource 6", id: "R6", capacity: 30},
    {name: "Resource 7", id: "R7", capacity: 10},
    {name: "Resource 8", id: "R8", capacity: 20},
    {name: "Resource 9", id: "R9", capacity: 15},
  ];
  dp.events.list = [];

  dp.rowHeaderColumns = [
    {name: "Name", display: "name", sort: "name", width: 100},
    {name: "Capacity", display: "capacity", sort: "capacity"},
  ];
  dp.onBeforeRowHeaderColumnRender = function(args) {
      var useCustomIcons = elements.customIcons.checked;

      if (useCustomIcons) {
        args.column.sortingEnabled = false;
        args.column.areas = [
          {
            right: 4,
            top: 10,
            height: 17,
            width: 10,
            icon: "fa fa-sort",
            style: "cursor: pointer",
            onClick: function() {
              dp.rows.sort({
                field: args.column.data.sort,
                order: (dp.rows.sortParam.field === args.column.data.sort && dp.rows.sortParam.order === "asc") ? "desc": "asc"
              });
            }
          }
        ];

      }
      else {
        if (args.column.data.name === "Capacity") {
          args.column.sortingEnabled = !elements.disableCapacity.checked;
        }
      }
  };

  dp.init();
</script>


</body>
</html>