Date picker on Service Portal - sideBySide

Alex Macdonel
Tera Expert

On the Service Portal the date time picker is very nice but our users have told us that when they use the arrows to increase the hours they sometimes don't notice that the date changed and this causes problems.

The Options - Bootstrap 3 Datepicker   tell me we can show both date and times side by side but now the question is, how can I enable this behavior in the Portal?

find_real_file.png

23 REPLIES 23

Mister Jim
Tera Contributor

I know this post is a few years old, but I wanted to share my solution for the sideBySide setting for future visitors. I was able to easily apply this portal-wide for our catalog item variables by putting the following line into the portal header's client script:

$.fn.datetimepicker.defaults.sideBySide = true;

 

Alternatively, this could probably be added to the specific page/widget (widget-sc-cat-item-v2 for instance) you are using to reduce the scope.

Hey guys, I wanted to share with you another possible solution I found to modify the behavior of the Date time picker widget through an OnLoad catalog client script, without having to modify the actual widget for everyone.

I was able to access the date time picker angular element through the window object and modify the default configurations to have the sideBySide property set as true.

 

"function onLoad() {

    var win = (0,eval)('this');

    win.angular.element("#datetimepicker").datetimepicker.defaults.sideBySide = true;

}"

 

Hope this could be helpful for someone

Giulioneri1
Tera Contributor

Hey guys, I wanted to share with you another possible solution I found to modify the behavior of the Date time picker widget through an OnLoad catalog client script, without having to modify the actual widget for everyone.

I was able to access the date time picker angular element through the window object and modify the default configurations to have the sideBySide property set as true.

 

function onLoad() {

    var win = (0,eval)('this');

    win.angular.element("#datetimepicker").datetimepicker.defaults.sideBySide = true;

}

 

Hope this could be helpful for someone

Joe1
Tera Expert

Here's what I ended up going with. I think I started using this last summer and it's been great ever since.

I created a Variable Set for each picker I need. For example, a "start time" one. I did a Single Row one with two columns alternating sides so that it will take only a single row on desktops but on phones will be responsive.

Joe1_0-1713384821805.png

 

Each Variable Set contains two variables. I am using "select_the_start_date" which is a Date type and "select_the_start_time" which is a Select Box type. For both of these, I leave them as optional and make them mandatory through the Catalog Item's UI Policies so I can use them in various ways across other Catalog Items. For the time select box, ensure it has no choice table and "Include none" is checked. Do not put any times in here as options!

 

Add the Variable Set to your Catalog Item. Create a new Catalog Client Script called "time picker - start" set to run on all UI Types, all views, and onLoad. It must also apply to the Catalog Item instead of the Variable Set.

 

Here is my script:

function onLoad() {
  var variableName = 'select_the_start_time'; // Replace '<variable_name>' with the actual variable name
  var timeIncrement = 30; // Set the time increment in minutes
  
  var startTime = new Date();
  startTime.setHours(0, 0, 0, 0); // Set the starting time
  
  var endTime = new Date();
  endTime.setHours(23, 59, 0, 0); // Set the ending time to 23:59:00
  
  var currentTime = new Date(startTime);
  
  while (currentTime <= endTime) {
    var label = formatTime(currentTime, false); // Format the time value as desired (12-hour format without seconds)
    var value = formatTime(currentTime, true); // Format the time value in 24-hour format with seconds
    
    g_form.addOption(variableName, value, label); // Add option to the select box variable
    
    currentTime.setMinutes(currentTime.getMinutes() + timeIncrement);
  }
}

function formatTime(date, is24HourFormat) {
  var hours = date.getHours();
  var minutes = date.getMinutes();
  var seconds = date.getSeconds();
  
  var formattedHours = padNumber(hours);
  var formattedMinutes = padNumber(minutes);
  var formattedSeconds = padNumber(seconds); // Pad seconds with leading zeros
  
  if (!is24HourFormat) {
    var amOrPm = hours >= 12 ? 'PM' : 'AM';
    formattedHours = convertTo12HourFormat(hours);
    return formattedHours + ':' + formattedMinutes + ' ' + amOrPm;
  }
  
  return formattedHours + ':' + formattedMinutes + ':' + formattedSeconds;
}

function convertTo12HourFormat(hours) {
  var suffix = hours >= 12 ? 'PM' : 'AM';
  var formattedHours = hours % 12;
  formattedHours = formattedHours === 0 ? 12 : formattedHours;
  
  return formattedHours.toString();
}

function padNumber(number) {
  return number < 10 ? '0' + number : number.toString();
}

This script will populate the dropdown options on the time picker variable. You can adjust the range of time available by setting the variables 'startTime.setHours' and 'endTime.setHours' if you want to limit the picker to, say, normal work hours. But here's another trick: you can adjust 'var timeIncrement = 30' to the interval, in minutes, that you need. So if you want 5 minutes between options, you can do that.

 

This script will present the times in the dropdown in a 12-hour AM/PM format:

Joe1_1-1713385877539.png

The time in the output is provided in a 24-hout format, so 2 AM would be recorded as the value 02:00:00 and 2 PM is recorded as 14:00:00. This may need to be changed to match your instance's defaults but I don't know.

 

If you want to do multiple of these time selectors on one Catalog Item, each one needs its own script. You can reuse these dropdowns in other Catalog Items but you will need to put the scripts in each Catalog Item.

 

I then have a Custom Action in Flow Designer that is designed to handle the input and merge the date and time into a single value. This probably could just be done with Flow Variables, but that's not how I have it set up. Besides, a Custom Action is easily reusable.

 

Inputs:

LabelNameTypeMandatory
DatedateDateYes
TimetimeString

Yes

 

Script step:

Create Input Variables 'date' and 'time' using there respective inputs. Create a string output called 'output' because you are just ready to move on to copying-and-pasting this script:

(function execute(inputs, outputs) {
  // Get the inputs
  var date = inputs.date;
  var time = inputs.time;

  // Stringify the inputs
  var dateString = date.toString();
  var timeString = time.toString();

  // Generate the date/time output string
  var outputString = dateString + " " + timeString;

  // Set the output variable
  outputs.output = outputString;
})(inputs, outputs);

 

Now, configure Outputs: I simply have the output of the Script Step be set in a Date/Time output.

 

This will now give you a nice, clean Date/Time data pill to use in your Flow. The date and time will stay the exact same values as in the input, so you should not need to worry about the system changing it a few hours because of time zone stuff. That being said, all our users really are only in one time zone, so I am not sure how well this works cross timezone. If someone uses this and has users in different time zones, let me know!

 

 

Now, what if you need to ensure that an end time is after a start time?
Create another Catalog Client Script like the first. Name it whatever. Here is the script:

function onSubmit() {
    var startDate = g_form.getValue('select_the_start_date');
    var startTime = g_form.getValue('select_the_start_time');
    var endDate = g_form.getValue('select_the_end_date');
    var endTime = g_form.getValue('select_the_end_time');

    // Convert date strings to Date objects
    var startDateTime = new Date(startDate + ' ' + startTime);
    var endDateTime = new Date(endDate + ' ' + endTime);

    // Check if end date is before start date and time
    if (endDateTime <= startDateTime) {
        if (endDate === startDate) { // Check if end date is the same as start date
			g_form.hideErrorBox('select_the_end_time');
			g_form.hideErrorBox('select_the_end_date');
            g_form.showErrorBox('select_the_end_time', 'The end time must be after the start time.');
        } else {
			g_form.hideErrorBox('select_the_end_time');
			g_form.hideErrorBox('select_the_end_date');
            g_form.showErrorBox('select_the_end_date', 'The end date must be after the start date.');
            g_form.showErrorBox('select_the_end_time', 'The end time must be after the start time.');
        }
        return false; // Block submission
    }

    return true; // Allow submission
}

This will block the submission of a Catalog Item until the end date and time is after the start date and time.

 

 

 

I hope this helps. This was a massive quality-of-life improvement for my users. I'm just now getting ready to roll out the end time validation, but I think that this is the solution to a lot of our time picker problems. And yes, I did use ChatGPT on this!