Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change date range to show events in FullCalendar

I need to be able to set a "date range" with FullCalendar, using the "List" view. By date range, I mean being able to enter using 2 text fields, 2 different dates, for example :

Text field 1 : 2018-05-05

to

Text field 2 : 2018-05-06

And to filter the content of the calendar, using the List view to display the result, and show events that matches that date range.

Here's my code for the FullCalendar part:

 $('#calendar').fullCalendar({
      header: {
        left: 'prev,next today',
        center: 'title',
        right: 'listMonth, month,agendaWeek,agendaDay'
      },
      defaultView: 'listMonth',
      locale: 'fr',
      contentHeight: 600,
      navLinks: true, // can click day/week names to navigate views
      selectable: false,
      eventRender: function(event, element, view) { 
        element.find('.fc-widget-header').append("<div style='color:#fff'>Conférencier choisi</div>");
        element.find('.fc-title').append("<br/>" + event.lieu); 
        element.find('.fc-list-item-title').append("<br/>" + event.lieu); 
        element.find('.fc-list-item-title').append("<a href='" + event.lienconferencier + "'><div class='conferencier-calendrier-container'><div style='float:left;background-image:url(" + event.photoconferencier + ");width:40px;height:40px;background-size:cover;border-radius:100px;'></div><div style='float:left;padding-left:5px;font-weight:normal;'><strong>Conférencier</strong><br>" + event.conferencier + "</div></a>"); 
          return ['all', event.status].indexOf($('#filter-status').val()) >= 0 &&
             ['all', event.client].indexOf($('#filter-contact').val()) >= 0 && 
             ['all', event.conferencier].indexOf($('#filter-conferencier').val()) >= 0 &&
             ['', event.numero].indexOf($('#numero').val()) >= 0;

      },
      selectHelper: true,
      editable: false,
      eventLimit: true, // allow "more" link when too many events
      events: [
        {
          title: 'Example',
          start: '2018-05-05',
          end: '2018-05-06',
          color: '#ff0000',
          lieu: 'Montreal',
          numero: '300445',
          conferencier: 'John Doe',
          photoconferencier: 'http://www.example.com/img/profile.jpg',
          lienconferencier: 'http://www.example.com/profile/link.html',
          url: 'http://www.google.com'
        },
{
          title: 'Example2',
          start: '2018-05-08',
          end: '2018-05-010',
          color: '#ff0000',
          lieu: 'New York',
          numero: '300446',
          conferencier: 'Steve Jobs',
          photoconferencier: 'http://www.example.com/img/profile2.jpg',
          lienconferencier: 'http://www.example.com/profile/link2.html',
          url: 'http://www.apple.com'
        },
      ],
    });

And here's my text fields code:

<input type="text" placeholder="Date : From" id="start_date">
<input type="text" placeholder="Date : To" id="end_date">

I think I would have to add something like this:

$('#start_date').on('change', function () {
                $('#calendar').fullCalendar('rerenderEvents');
            });
$('#end_date').on('change', function () {
                $('#calendar').fullCalendar('rerenderEvents');
            });

But I am not sure. Also, please keep in mind that there's other filters too. Hence the "eventRender" part in the code with a bunch of stuff. So I need to make sure that "dateRange" filter won't break the other filters.

I read about "visibleRange" on FullCalendar's website, but I do not understand how I can make it work based on what is entered in the 2 "date range" text fields. I think also disabling the other views that I have set (to show the result in the List view only), would be a good idea.

Any idea how I can make it work? I'm kind of lost here. Thanks a lot


EDIT :

I have tried this code:

$('#start_date').on('change', function () {
      $('#calendar').fullCalendar('changeView', 'list', {
        start: 2018-05-10,
        end: 2018-05-30
      });            
});

Which is working. Basically, what it does is that I enter a new date in a text field with the ID of "start_date" (which uses a datepicker script, to that's why I went with "on change"), it changes the view to the list view, which is great, and displays only the events between the date I have entered. So to make it dynamic, I did this :

$('#start_date').on('change', function () {
  var start_date = $('#start_date').val();
  var end_date = $('#end_date').val();
      $('#calendar').fullCalendar('changeView', 'list', {
        start: start_date,
        end: end_date
      });            
});

I have 2 fields, "start_date", and "end_date". I thought that setting the "start" and "end" option in the changeView code for FullCalendar would update automatically everytime I select a new date, but it doesn't work. In fact, it works partially. If I enter the "end_date" first, then the "start_date", it will filter and work perfectly, showing the right date range. But after that, I cannot change it for another dateRange by changing the dates in the fields. It acts like this probably because my function is "on change", based on the "#start_date" element. So I have to select the end_date first, to make sure it filters and change the view with something in the "end" option.

Any idea what I am doing wrong?

Thanks


EDIT 2 :

I tried changing the function from a "change" event to "click", and adding a "search" button. There's 2 issues here. 1 - It works only once. If I make a search, then change the date, and click again on the "#search-range" button, it won't do anything.

2 - When it works (first time after page load), if I select from May 1rst to May 5th for example, it will show the range from May 1rst to May 4th, for some reasons. Here's my code again :

$('#search-range').on('click', function () {
  var start_date = $('#start_date').val();
  var end_date = $('#end_date').val();
  $('#calendar').fullCalendar('changeView', 'list', {
        start: start_date,
        end: end_date
      });            
});

Any ideas what's going on? Thanks again

like image 734
larin555 Avatar asked Oct 16 '22 18:10

larin555


1 Answers

You're probably looking for the validRange option.

$('#start_date').on('change', function(){
  $('#calendar').fullCalendar('option', 'validRange', {
    // Don't worry if user didn't provide *any* inputs.
    start: this.value,
    end: $('#end_date').val()
  });
});

$('#end_date').on('change', function(){
  $('#calendar').fullCalendar('option', 'validRange', {
    // Don't worry if user didn't provide *any* inputs.
    start: $('#start_date').val(),
    end: this.value
  });
});

Demo: https://jsfiddle.net/8wd7sxyv/

UPDATE

  • The end date is now inclusive. So if end date is 2018-05-31, events on that day are included — the default behavior only includes up to 2018-05-30.
  • If the start and end dates are in same month, view is listMonth; otherwise, it is listYear.
  • function filterByDateRange(start_date, end_date, format) {
      var s = $.fullCalendar.moment(start_date),
          e = $.fullCalendar.moment(end_date),
          v = $('#calendar').fullCalendar('getView'),
          a, b;
    
      // Start date is invalid; set it to the start of the month.
      if (! s.isValid()) {
        b = e.isValid();
        s = b ? e.clone() : $.fullCalendar.moment();
        s.date(1);
        $('#start_date').val(s.format(format));
        a = true;
      }
      // End date is invalid; set it to the end of the month.
      if (! e.isValid()) {
        b = s.isValid();
        e = b ? s.clone() : $.fullCalendar.moment();
        e.date(e.daysInMonth());
        $('#end_date').val(e.format(format));
        a = true;
      }
    
      // Start date is after end date; set it to a day before the end date.
      if (s.isAfter(e)) {
        s = e.clone().add('-1', 'day');
        $('#start_date').val(s.format(format));
      // End date is before start date; set it to a day after the start date.
      } else if (e.isBefore(s)) {
        e = s.clone().add('1', 'day');
        $('#end_date').val(e.format(format));
      }
    
      // Add 1 day so that `end_date` is inclusive.
      e = e.isValid() ? e.add('1', 'day') : e;
    
      $('#calendar').fullCalendar('option', 'validRange', {
        start: s.isValid() ? s : null,
        end: e.isValid() ? e : null
      });
    
      a = a || s.isSame(e, 'month');
      // If months are different, switch to the year list.
      if ('listYear' !== v.name && ! a) {
        $('#calendar').fullCalendar('changeView', 'listYear');
      // Otherwise, switch back to month list, if needed.
      } else if ('listMonth' !== v.name) {
        $('#calendar').fullCalendar('changeView', 'listMonth');
      }
    }
    
    $('#start_date').on('change', function(){
      filterByDateRange(this.value, $('#end_date').val(), 'YYYY-MM-DD');
    });
    
    $('#end_date').on('change', function(){
      filterByDateRange($('#start_date').val(), this.value, 'YYYY-MM-DD');
    });
    

    Demo: https://jsfiddle.net/8wd7sxyv/6/

    like image 189
    Sally CJ Avatar answered Oct 30 '22 02:10

    Sally CJ