How to create to filter results using custom date widget

Hello,
I’m trying to build a search by date and I need to follow this design:

<div class="filters-content--header">
    <p>Event Date</p>
    <i class="fa fa-angle-down"></i>
</div>
<div class="filter-content--options">
    <div class="date-field--wrapper">
        <span>From</span>
        <label for="date" class="date-label"></label>
        <input id="date" class="date-input" type="date" placeholder="Search here...">
    </div>
    <div class="date-field--wrapper">
        <span>Until</span>
        <label for="date" class="date-label"></label>
        <input id="date" class="date-input" type="date" placeholder="Search here">
    </div>
</div>

I’ve searched you guides and the web and can’t find a way to make this.
In my index I have this:
timestampBeginDate:1525903200
endDate:2018-May-15
timestampEndDate:1526335200
How to search with the numeric filter using the timestamps from my index and maintaining my design, can you provide an example?

Hi did you have a look at our calendar guide?

Have a look and if something is not working for you, provide us a live example using our template with what you tried and failed.

Thanks!

Hello,
I’ve followed your calendar guide and I can make it work, although is not working 100% as I intend.

Here is a link for a jsfiddle https://jsfiddle.net/daniel_santos/opk9vetL/19/

Let’s say an event has a begin date of 2018-May-10 and a end date of 2018-May-15
If I search between 2018-May-09 and 2018-May-16 it shows me the event in the results but if I search between 2018-May-11 and 2018-May-13 it should show me the same event like the first search but it does not show any results.
Do I have to send to Algolia all dates on which the event occurs?
Thank you for the support.

Hi @daniel.santos You have two options to achieve what you want here:

1. Duplicate events

If your event is spread on multiple days, you could create one event object per day like so:

[{
  objectID: ..
  eventID: ..,
  eventTimestamp: dayOneTimestamp
}, {
  objectID: ..,
  eventID: ..,
  eventTimestamp: dayTwoTimestamp
}]

and then use:

By doing so you can keep most of your code but there will be duplication in your index.

2. Use something else than connectRange

connectRange was not meant to be used in a situation where your range is on multiple attributes. But you can always create a complete custom widget like so: https://community.algolia.com/instantsearch.js/v2/guides/custom-widget.html

By doing so, and by using numeric filters directly on the helper: https://community.algolia.com/algoliasearch-helper-js/reference.html#numeric-filters you will be able to craft queries like: “List events starting before or on May 6th and ending the 8th or after”. Which should list you all events occurring between two dates.

Let us know how it goes.

Thanks for bringing this use case, definitely one where we need to be better at.

Hello,
thank you for you help.

What I’ve done to solve is I’m sending to Algolia an array with each day the event occurs as timestamp, then I use instantsearch.connectors.connectRange. It’s not perfect and since the events will have a maximum 5 days durantion it works fine for my purpose, just be aware of timezones differences.

I can provide an example if someone find useful.

Thank you and great search.

Yes it would be VERY useful to get your solution as an example if you can provide this. Thanks so much for feedback!

Hello,
here is an example of the solution I implemented:

  const makeRangeWidget = instantsearch.connectors.connectRange(
  (options, isFirstRendering) => {
    if (!isFirstRendering) return;

    const { refine } = options;
    var dateBegin;
    var formattedBeginDate;
    var dateEnd;
    var formattedEndDate;
   
    $("input[type='date']").change(function() {
       dateBegin = $('#date1').val();
       dateEnd = $('#date2').val();
       /* date / 1000 for miliseconds to seconds conversion 
       *  -/+ 3601 for same day search and -/+ 1 hour for DST */
       formattedBeginDate = (new Date(dateBegin)).getTime() / 1000 - 3601;
       formattedEndDate = (new Date(dateEnd)).getTime() / 1000 + 3601;
       if (isNaN(formattedEndDate)) {
           refine([formattedBeginDate]); // get all events from this date
       } else if(isNaN(formattedBeginDate)){
           refine([0, formattedEndDate]); // get all events until this date
       } else {
           refine([formattedBeginDate, formattedEndDate]); // get all events between these dates
       }
   });
  }
);

const dateRangeWidget = makeRangeWidget({
  attributeName: 'allDates',
}); 

search.addWidget(dateRangeWidget);

Note that the records in my index have an attribute formatted like this:
‘allDates’: [1523833200, 1523919600, (…)]
Inside the array ‘allDates’ is the unix timestamp for each day the event occurs.
In my view I have 2 datepickers, 1 for start date (#date1) and the other for end date (#date2)

Hope this helps someone.