You are viewing limited content. For full access, please sign in.

Question

Question

Lookup table results not appearing in restricted date picker

asked on August 10, 2021 Show version history

I am working on a form for the public to select an available date for a service.  I used the code laid out in this thread to restrict available dates (the service is only offered M, W, F), and added a lookup rule to the form that looks up a sql table with dates that have already been taken.  The "blackoutDates hiddenField" drop down on the form uses the "Append choices to lookup results", and when I unhide the field I can see that the correct choices do appear in the drop down.  So the lookup rule is working, but my calendar is not excluding the dates in the table.  Below is what I have in my "CSS and JavaScript" section.  It's like only the first half of line 30 is recognized.

I'm thinking it has something to do with the format of the date field in my lookup table.  I have tried "date" type and "text", both have the same result. 

//Create the array of blackout dates
var blackoutDatesList = new Array();

//Run the function when the document loads
$(document).ready(function(){
  
  //Set the date range to only display available future dates for 180 days
  var today = new Date();
  var startDate = new Date();
  startDate.setDate(today.getDate() + 1);
  var endDate = new Date();
  endDate.setDate(today.getDate() + 180);
  var minDate = $.datepicker.formatDate('yy-mm-dd', new Date(startDate));
  var maxDate = $.datepicker.formatDate('yy-mm-dd', new Date(endDate));
  $('.myLimitedDate input').attr('min', minDate);
  $('.myLimitedDate input').attr('max', maxDate);

  //loop through each date in the blackout date list, and add it to an array
  blackoutDatesList.length = 0;
  $('.blackoutDates option').each(function() {
    blackoutDatesList.push(formatDate(new Date($(this).val())));
  });

  //disable other dates on the picker that are not M, W, F or are in the blackout array
  //add validation setting for date format
  function isValidDate(n) {
    var t = n.getDay();
    var d = n.getDate();
    var string = jQuery.datepicker.formatDate('yy-mm-dd', n);
    return (t!=0 && t!=2 && t!= 4 && t!=6 && blackoutDatesList.indexOf(string) == -1);
  }

function checkDate(n) {
    return[isValidDate(n),""];
  }
  function checkField(input, inst) {
    if ($(input).closest('li').hasClass('myLimitedDate')) {
      $(input).datepicker("option", {beforeShowDay: checkDate});
    }
  }
  $.datepicker.setDefaults( {beforeShow: checkField} );
  window.Parsley.addValidator('limiteddate', {
    validateString: function(value) {
      //IMPORTANT! this date format needs to match the format you set for the field on the layout page
      return isValidDate(moment(value, "mm-DD-yyyy").toDate()); 
    },
    messages: {
      en: 'Not a valid date.'
    }
  });
  $('.myLimitedDate input').attr('data-parsley-limiteddate','');
});
 
//this function is run when the lookups are completed.
$(document).on("onloadlookupfinished", function () {
  //loop through each date in the blackout date list, and add it to an array
  blackoutDatesList.length = 0;
  $('.blackoutDates option').each(function() {
    blackoutDatesList.push(formatDate(new Date($(this).val())));
  });
});
 
//function to return any date formatted as yyyy-mm-dd
function formatDate(date) {
  var d = new Date(date),
    month = '' + (d.getMonth() + 1),
    day = '' + (d.getDate() +1),
    year = d.getFullYear();
  if (month.length < 2) 
    month = '0' + month;
  if (day.length < 2) 
    day = '0' + day;
  return [year, month, day].join('-');
}

 

0 0

Replies

replied on August 10, 2021

Are you sure your blackoutDatesList variable is being populated properly and in the expected format?

Your "string" variable on line 29 seems to be using 'yy-mm-dd' format, but on line 63 your formatDate function says it is returning the value in 'yyyy-mm-dd' format.

If you utilize the moment.js library already available in Forms, you can eliminate that separate date formatting function. Moment.js | Home (momentjs.com)

For example,

// current date in "yy-MM-dd" format
moment(new Date()).format('YY-MM-DD');

// any date string (input) in "yyyy-MM-dd" format
moment(new Date(input)).format('YYYY-MM-DD');

The first thing I would recommend doing is to open your form, then open up the dev console and just type blackoutDatesList and hit Enter.

Since you're using a global variable you should be able to view the array's values in the console to make sure it is being populated, and that the format matches what your checking against.

 

Also, it's not necessary to use new Array(). The literal notation for a new array is usually more efficient and more readable like, var blackoutDatesList = [];

0 0
replied on August 10, 2021

Thanks for the tips, I am definitely a JavaScript novice.

I did as you suggested and opened the form, typed in "blackoutDatesList" in the dev tools console, and all of the dates appeared and in the correct format.

Changing the format on line 29 seems to just make the datepicker recognize any date entered as invalid.  I went back into the form and changed the format of the date field to match the format in that line of code, and it still just seems to reject every date as invalid. 

The calendar is blocking out all dates prior to today and everything other than M, W, F, which is what I expect, but the dates on my blackout list are still showing up as available.

0 0
replied on August 10, 2021 Show version history

Add this after line 29 and check the dev console when you change the date.

console.log(string);

Although the 'yy-mm-dd' format may be correct for validating your other days, I suspect the reason your list isn't working is because those dates are not in the same format.

If that's the case, then you need to format the entries in your array to match rather than changing the format you use on line 29.

For example, by changing line 59 to:

blackoutDatesList.push(moment(new Date($(this).val())).format('YY-MM-DD'));

0 0
replied on August 11, 2021

I think you're right.  I get an error "format is not a function" when using the ".format('YY-MM-DD')" though.  Any ideas?

0 0
replied on August 11, 2021

Can you post the line of code that caused the error and the exact error message? It's hard to say what might be causing it without more information.

.format() is a method for moment, and requires the following syntax

moment(date).format('format');

0 0
replied on August 11, 2021

That was my mistake, I did not call the moment function.  I revised the code and am not getting that error, but the dates from my blackout list still aren't coming through.

I am wondering if it is reading the header from the table.  When I enter "blackoutDatesList" in dev tools, it now shows the first item as "Invalid Date".

0 0
replied on August 11, 2021

If your dropdown is not required, then the first item in the select options will have no value (empty selection).

To get around that change your selector on line 20 to

$('.blackoutDates option[value]').each(function() {

Then it will ignore anything that doesn't have a value populated.

 

Also, note that your blackout date list values are in MM/dd/yyyy format.

Your blackoutDatesList.indexOf(string) check on line 30 is using a value in yy-mm-dd format (line 29) so it will never find a match.

indexOf is comparing the string values, so '08/12/2021' != '21-08-12'

You need both values to be in the same format to find a string match.

0 0
replied on August 11, 2021

I have changed the format to mm-dd-yyyy throughout my script, maybe that is the problem?  I added the [value] to the selector and still no luck.  Here is what the updated section looks like now:


  //loop through each date in the blackout date list, and add it to an array
  blackoutDatesList.length = 0;
  $('.blackoutDates option[value]').each(function() {
    blackoutDatesList.push(moment(new Date($(this).val())).format('MM/DD/YYYY'));
  });

  //disable other dates on the picker that are not M, W, F or are in the blackout array
  //add validation setting for date format
  function isValidDate(n) {
    var t = n.getDay();
    var d = n.getDate();
    var string = jQuery.datepicker.formatDate('MM/DD/YYYY', n);
    return (t!=0 && t!=2 && t!= 4 && t!=6 && blackoutDatesList.indexOf(string) == -1);
  }

 

0 0
replied on August 11, 2021

In your isValidDate function, add the following code right after line 12 and before line 13 of your latest code snippet:

console.log(blackoutDatesList.join(', '));

console.log(string);

That will make testing easier because every time your validation check is triggered it will show the list of blackout dates in the console and the "string" value you're looking for in the list.

Another tip, when you're making changes and troubleshooting, reproduce everything you tested previously, like checking the variable list in the console, to see what may have changed. Sometimes things still don't work but they fail in a different way, which can help steer you in the right direction.

1 0
replied on August 11, 2021 Show version history

Thank you so much, I am making progress finally!

It IS working to a degree.  Basically, it is not blocking out the dates in my blackoutDates table, but it is returning the error "not a valid date" when a date from the table is selected.

Here is an example, the date 8/13/2021 is on the blackoutDates list:

But it is working to block out all days other than M, W, F

  //loop through each date in the blackout date list, and add it to an array
  blackoutDatesList.length = 0;
  $('.blackoutDates option[value]').each(function() {
    blackoutDatesList.push(moment(new Date($(this).val())).format('MM/dd/yyyy'));
  });

  //disable other dates on the picker that are not M, W, F or are in the blackout array
  //add validation setting for date format
  function isValidDate(n) {
    var t = n.getDay();
    var d = n.getDate();
    var string = jQuery.datepicker.formatDate('MM/dd/yyyy', n);
    console.log(blackoutDatesList.join(','));
    console.log(string);
    return (t!=0 && t!=2 && t!= 4 && t!=6 && blackoutDatesList.indexOf(string) == -1);
  }

function checkDate(n) {
    return[isValidDate(n),""];
  }
  function checkField(input, inst) {
    if ($(input).closest('li').hasClass('myLimitedDate')) {
      $(input).datepicker("option", {beforeShowDay: checkDate});
    }
  }
  $.datepicker.setDefaults( {beforeShow: checkField} );
  window.Parsley.addValidator('limiteddate', {
    validateString: function(value) {
      //IMPORTANT! this date format needs to match the format you set for the field on the layout page
      return isValidDate(moment(value, "MM/dd/yyyy").toDate()); 
    },
    messages: {
      en: 'Not a valid date.'
    }

 

0 0
You are not allowed to follow up in this post.

Sign in to reply to this post.