javascriptfullcalendarfullcalendar-5

I want to have two periods in the fullcalendar defined by slotMinTime and slotMaxTime


I intended to use two different periods in the same calendar. The only way to do it that I've found so far is to do it in two different calendars, where it looks like this:

$(".btn-show").click(function(e) {
  e.preventDefault();
  el = $(this).data('element');
  $(el).show();
  $("section > div").not(el).hide();
});

$(document).on('click', '.dad-visita', function(){
    if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
          initialViews = 'timeGridWeek';
     }else{
          initialViews = 'timeGridWeek';
     }  

     var calendarEl = document.getElementById('calendario');
     var today = moment().day();

     var calendar = new FullCalendar.Calendar(calendarEl, {
        
        headerToolbar: {
            left: 'prev,next today',
            center: 'title',
            right: 'dayGridMonth,timeGridWeek,timeGridDay'
        },
        locale: "pt-br",

        buttonText:{
            today:    'Hoje',
            list:     'Lista'
        },

        navLinks: true,             
        firstDay: today,
        hiddenDays: [ 0 ],
        initialView: initialViews,
        editable: true,
        selectable: true, 
        unselectAuto:true,
        eventOverlap: false,
        eventColor: '#f16621', 
        slotDuration: '00:45',
        allDaySlot : false,
        eventStartEditable: false,
        eventDurationEditable:false,
        longPressDelay: 0,
        nowIndicator: "true",
        slotMinTime: '10:30',
        slotMaxTime: '12:00',
        contentHeight: 'auto',
        
                

    });

    calendar.render();
});

$(document).on('click', '.dad-visita', function(){
    if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
          initialViews = 'timeGridWeek';
     }else{
          initialViews = 'timeGridWeek';
     }  

     var calendarEl = document.getElementById('calendario1');
     var today = moment().day();

     var calendar = new FullCalendar.Calendar(calendarEl, {
        
        headerToolbar: {
            left: 'prev,next today',
            center: 'title',
            right: 'dayGridMonth,timeGridWeek,timeGridDay'
        },
        locale: "pt-br",

        buttonText:{
            today:    'Hoje',
            list:     'Lista'
        },

        navLinks: true,             
        firstDay: today,
        hiddenDays: [ 0 ],
        initialView: initialViews,
        editable: true,
        selectable: true, 
        unselectAuto:true,
        eventOverlap: false,
        eventColor: '#f16621', 
        slotDuration: '00:45',
        allDaySlot : false,
        eventStartEditable: false,
        eventDurationEditable:false,
        longPressDelay: 0,
        nowIndicator: "true",
        slotMinTime: '14:30',
        slotMaxTime: '19:00',
        contentHeight: 'auto',

    });

    calendar.render();
});
<link href="https://cdn.jsdelivr.net/npm/fullcalendar@5.9.0/main.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.9.0/main.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/locale/pt-br.js"></script>

<a href="s160" data-element="#minhaDiv160" class="btn-show dad-visita">
    <i class="metismenu-icon pe-7s-info"></i>
    Consultar Visitas
</a>

<section id="s160">
  <div style="display:none;" id="minhaDiv160">
    <div class="cal-wrapper"><div id='calendario'></div></div>
    <div class="cal-wrapper"><div id='calendario1'></div></div>
  </div>
</section>

But this way I have to have two calendars, which is not the correct way. The reason I have to do this is that I need the slotDuration to be 45 minutes and in the morning it assumes the time of events correctly.

But the afternoon events start at 14:30 and with this slotDuration the calendar in the afternoon event starts at 14:15 if you set the slotMinTime at 10:30 and the slotMaxTime at 19:00, as shown in the example:

$(".btn-show").click(function(e) {
  e.preventDefault();
  el = $(this).data('element');
  $(el).show();
  $("section > div").not(el).hide();
});

$(document).on('click', '.dad-visita', function(){
    if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
          initialViews = 'timeGridWeek';
     }else{
          initialViews = 'timeGridWeek';
     }  

     var calendarEl = document.getElementById('calendario');
     var today = moment().day();

     var calendar = new FullCalendar.Calendar(calendarEl, {
        
        headerToolbar: {
            left: 'prev,next today',
            center: 'title',
            right: 'dayGridMonth,timeGridWeek,timeGridDay'
        },
        locale: "pt-br",

        buttonText:{
            today:    'Hoje',
            list:     'Lista'
        },

        navLinks: true,             
        firstDay: today,
        hiddenDays: [ 0 ],
        initialView: initialViews,
        editable: true,
        selectable: true, 
        unselectAuto:true,
        eventOverlap: false,
        eventColor: '#f16621', 
        slotDuration: '00:45',
        allDaySlot : false,
        eventStartEditable: false,
        eventDurationEditable:false,
        longPressDelay: 0,
        nowIndicator: "true",
        slotMinTime: '10:30',
        slotMaxTime: '19:00',
        contentHeight: 'auto',

    });

    calendar.render();
});
<link href="https://cdn.jsdelivr.net/npm/fullcalendar@5.9.0/main.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.9.0/main.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/locale/pt-br.js"></script>

<a href="s160" data-element="#minhaDiv160" class="btn-show dad-visita">
    <i class="metismenu-icon pe-7s-info"></i>
    Consultar Visitas
</a>

<section id="s160">
  <div style="display:none;" id="minhaDiv160">
    <div class="cal-wrapper"><div id='calendario'></div></div>
    <div class="cal-wrapper"><div id='calendario1'></div></div>
  </div>
</section>

When starting at 14:15, it soon returns the times of all the different afternoon events with what I want.

I still couldn't find a solution to solve this problem.

Code with selectAllow:

$(".btn-show").click(function(e) {
  e.preventDefault();
  el = $(this).data('element');
  $(el).show();
  $("section > div").not(el).hide();
});

$(document).on('click', '.dad-visita', function(){
    if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
          initialViews = 'timeGridWeek';
     }else{
          initialViews = 'timeGridWeek';
     }  

     var calendarEl = document.getElementById('calendario');
     var today = moment().day();

     var calendar = new FullCalendar.Calendar(calendarEl, {
        
        headerToolbar: {
            left: 'prev,next today',
            center: 'title',
            right: 'dayGridMonth,timeGridWeek,timeGridDay'
        },
        locale: "pt-br",

        buttonText:{
            today:    'Hoje',
            list:     'Lista'
        },

        navLinks: true,             
        firstDay: today,
        hiddenDays: [ 0 ],
        initialView: initialViews,
        editable: true,
        selectable: true, 
        unselectAuto:true,
        eventOverlap: false,
        eventColor: '#f16621', 
        slotDuration: '00:15',
        allDaySlot : false,
        eventStartEditable: false,
        eventDurationEditable:false,
        longPressDelay: 0,
        nowIndicator: "true",
        slotMinTime: '10:30',
        slotMaxTime: '19:00',
        contentHeight: 'auto',
        
        select: function(start, end) {
            var start1 = moment((start.startStr)).format('HH:mm:ss');
            if(start1 == '14:15:00'){            
             
            $('#ModalAddVisit #start').val(moment((start.startStr)).format('YYYY-MM-DD' + " " + '14:30:00'));
            $('#ModalAddVisit #end').val(moment((start.startStr)).format('YYYY-MM-DD' + " " + '15:15:00'));
            $("#ModalAddVisit").modal("show");
            }

            
        },

    });

    calendar.render();
});
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css">
<link href="https://cdn.jsdelivr.net/npm/fullcalendar@5.9.0/main.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.9.0/main.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/locale/pt-br.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js"></script>

<a href="s160" data-element="#minhaDiv160" class="btn-show dad-visita">
    <i class="metismenu-icon pe-7s-info"></i>
    Consultar Visitas
</a>

<section id="s160">
  <div style="display:none;" id="minhaDiv160">
    <div class="cal-wrapper"><div id='calendario'></div></div>
  </div>
</section>


<div class="modal fade" tabindex="-1" id="ModalAddVisit" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
  <div class="modal-dialog modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="exampleModalLabel">NOVA VISITA</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <form method="POST" class="row g-3 insvisit">
          <div class="row">
            <div class="col-6">
              <label for="start"> <strong>DATA/HORA INICIAL</strong> <span style="color: red;">*</span></label>
              <input type="text" name="start" id="start" required>
            </div>
            <div class="col-6">
              <label for="end"> <strong>DATA/HORA FINAL</strong> <span style="color: red;">*</span></label>
              <input type="text" name="end" id="end" required>
            </div>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Fechar</button>
            <button type="button" class="btn btn-primary validatevisit" id="save-event">Gravar</button>
          </div>
        </form>
      </div>
    </div>
  </div>
</div>


Solution

  • FullCalendar doesn't let you set two different min and max values on the same calendar.

    To work round this, but still achieve your goal of enforcing 45-minute slots, with a break in the middle of day where no events can be created, you can

    $(".btn-show").click(function(e) {
      e.preventDefault();
      el = $(this).data('element');
      $(el).show();
      $("section > div").not(el).hide();
    });
    
    $(document).on('click', '.dad-visita', function() {
      if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
        initialViews = 'timeGridWeek';
      } else {
        initialViews = 'timeGridWeek';
      }
    
      var calendarEl = document.getElementById('calendario');
      var today = moment().day();
    
      var calendar = new FullCalendar.Calendar(calendarEl, {
        headerToolbar: {
          left: 'prev,next today',
          center: 'title',
          right: 'dayGridMonth,timeGridWeek,timeGridDay'
        },
        locale: "pt-br",
        buttonText: {
          today: 'Hoje',
          list: 'Lista'
        },
        navLinks: true,
        firstDay: today,
        hiddenDays: [0],
        initialView: initialViews,
        editable: true,
        selectable: true,
        unselectAuto: true,
        eventOverlap: false,
        eventColor: '#f16621',
        slotDuration: '00:15',
        allDaySlot: false,
        eventStartEditable: false,
        eventDurationEditable: false,
        longPressDelay: 0,
        nowIndicator: "true",
        slotMinTime: '10:30',
        slotMaxTime: '19:00',
        contentHeight: 'auto',
        selectConstraint: "businessHours",
        selectAllow: function(info) {
          var start = moment(info.start);
          var end = moment(info.end);
          var diff = end.diff(start, 'minutes');
          return (diff == 45);
        },
        businessHours: [
          {
            daysOfWeek: [0, 1, 2, 3, 4, 5, 6],
            startTime: '10:00',
            endTime: '12:00'
          },
          {
            daysOfWeek: [0, 1, 2, 3, 4, 5, 6],
            startTime: '14:30',
            endTime: '19:00'
          }
        ],
        select: function(info) {
          var start1 = moment((info.startStr)).format('HH:mm:ss');
          $('#ModalAddVisit #start').val(moment((info.startStr)).format('YYYY-MM-DD' + " " + '14:30:00'));
          $('#ModalAddVisit #end').val(moment((info.startStr)).format('YYYY-MM-DD' + " " + '15:15:00'));
          $("#ModalAddVisit").modal("show");
        }
      });
    
      calendar.render();
    });
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css">
    <link href="https://cdn.jsdelivr.net/npm/fullcalendar@5.9.0/main.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.9.0/main.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/locale/pt-br.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js"></script>
    
    <a href="s160" data-element="#minhaDiv160" class="btn-show dad-visita">
      <i class="metismenu-icon pe-7s-info"></i> Consultar Visitas
    </a>
    
    <section id="s160">
      <div style="display:none;" id="minhaDiv160">
        <div class="cal-wrapper">
          <div id='calendario'></div>
        </div>
      </div>
    </section>
    
    
    <div class="modal fade" tabindex="-1" id="ModalAddVisit" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
      <div class="modal-dialog modal-lg" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="exampleModalLabel">NOVA VISITA</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
          </div>
          <div class="modal-body">
            <form method="POST" class="row g-3 insvisit">
              <div class="row">
                <div class="col-6">
                  <label for="start"> <strong>DATA/HORA INICIAL</strong> <span style="color: red;">*</span></label>
                  <input type="text" name="start" id="start" required>
                </div>
                <div class="col-6">
                  <label for="end"> <strong>DATA/HORA FINAL</strong> <span style="color: red;">*</span></label>
                  <input type="text" name="end" id="end" required>
                </div>
              </div>
              <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Fechar</button>
                <button type="button" class="btn btn-primary validatevisit" id="save-event">Gravar</button>
              </div>
            </form>
          </div>
        </div>
      </div>
    </div>