0

I want to know how to repeat events from variable dates (start and end dates), weekly and monthly.

I found this answer, but it didn't work for me: Repeat fullcalendar events daily, monthly and yearly

This is my code:

function modal_activity_fun(info){

  let modal_activity = $("#modal_activity");

  function event_modal(){
  // for modal_activity
    modal_activity.on('show.bs.modal', function (e) { create_multiselect($('#activity_from')); });
    modal_activity.on('shown.bs.modal', function (e) { $('#activity_title').focus(); });
    modal_activity.on('hidden.bs.modal', function (e) {
      document.getElementById("activity_form").reset();
      $('#activity_from').multiselect('deselectAll', false);    
      $('#activity_from').multiselect('updateButtonText');
    })
  }
    
  function datepicker_modal(){
    // start datepicker
    modal_activity.find('#activity_start_date').datepicker({
      format: "DD, dd - MM - yyyy",
      language: "pt-BR"
    });
    modal_activity.find('#activity_end_date').datepicker({
      format: "DD, dd - MM - yyyy",
      language: "pt-BR"
    });

    $('#activity_start_date').datepicker('setDate', moment(info.startStr, 'YYYY-MM-DD').format('DD - MM - YYYY'));
    $('#activity_end_date').datepicker('setDate',  moment(info.endStr, 'YYYY-MM-DD').subtract(1, "days").format('DD - MM - YYYY'));
  }

  function add_activity(){
    // When 'add_activity' button is pressed, an event is created and the modal is closed
    $('#add_activity').off("click");
    $('#add_activity').on("click", info, function(e){
      let title = modal_activity.find("#activity_title").val();
      let btn = $(this);
      let total_empty = 0;
      let last_empty = '';

      $('input,textarea,select').filter('[required]:visible').each(function(){
        if($(this).val()==''){total_empty += 1; last_empty=$(this);}
      });
      let form = $(this).parents('.modal-content');

      if (form.find("#activity_from").val().length == 0 ){
        if (last_empty == ""){
          last_empty = $('.dropdown-toggle, .multiselect');
        }
        total_empty += 1;
        $('.dropdown-toggle, .multiselect').addClass("generic_focus");
      }

      if( total_empty == 0){
        let startStr = moment($('#activity_start_date').datepicker('getDate')).format('YYYY-MM-DD');
        let endStr = moment($('#activity_end_date').datepicker('getDate')).add(1, "days").format('YYYY-MM-DD');
        let start_day_number = moment(startStr).subtract(1, "days").day();
        let end_day_number = moment(endStr).subtract(1, "days").day();
        


        let extendedProps = {
          description: form.find('#activity_description').val(),
          from: form.find('#activity_from').val(),
          repetition:  form.find('#activity_repetition option:selected' ).text(),
          status: "Scheduled",
        }

        let event_object = {title: title, start: startStr, end:endStr, allDay: true, extendedProps: extendedProps}

        let repetition = form.find('#activity_repetition').val();
        
        if(repetition == 3){
          event_object['repeat'] = 1;
        }
        if(repetition == 2){
          event_object['repeat'] = 0;
        }

        debugger;

        info.calendar.addEvent(event_object);

        modal_activity.modal('hide');
      }else{
        last_empty.focus();
        btn.popover("show");
        setTimeout(function(event) {btn.popover("hide")},3000);
      }
    });
  }

  function go(options='show'){
    modal_activity.modal(options);
  }

  function assemble(){
    event_modal();
    datepicker_modal();
    add_activity();
    go();
  }

  return {assemble}
}

function modal_activity_view_fun(info){

  let modal_activity_view = $('#modal_activity_view');
  let startStr = moment(info.event.startStr, 'YYYY-MM-DD').locale('pt-br');
  let endStr = moment(info.event.endStr, 'YYYY-MM-DD').locale('pt-br').subtract(1, "days");

  modal_activity_view.on('hidden.bs.modal', function (e) { $('#activity_repetition_view').html(); });

  function set_values(){
    modal_activity_view.find('.modal-title').text(info.event.title);
    modal_activity_view.find('#activity_description_view').html(info.event.extendedProps.description.replace(/\n/g, "</br>\n"));
    if(startStr.isSame(endStr)){
      modal_activity_view.find('#activity_schedule_view').html(startStr.format('dddd, DD [de] MMMM'));
    }else if(startStr.month() == endStr.month() && startStr.year() == endStr.year()){
      modal_activity_view.find('#activity_schedule_view').html(
          startStr.format('DD')+' – '+endStr.format('DD [de] MMMM')
      );
    }else{
      modal_activity_view.find('#activity_schedule_view').html(
        startStr.format('DD [de] MMMM [de] YYYY')+' – '+endStr.format('DD [de] MMMM [de] YYYY')
      );
    }
    debugger;
    if (info.event.extendedProps.repetition != "não se repete"){
      modal_activity_view.find('#activity_repetition_view').html('• '+info.event.extendedProps.repetition);
    }
    modal_activity_view.find("#activity_status_view").text(info.event.extendedProps.status)
  }

  function go(options='show'){
    modal_activity_view.modal(options);
  }
  
  function assemble(){
    set_values();
    go();
  }

  return {assemble}
}

function list_interval(start, end){
  let array = [];
  for(let i=start; i <= end; i++){
    array.push(i);
  }
  return array;
}

function fullcalendar_activities(){
    document.addEventListener('DOMContentLoaded', function() {
        var calendar_atv_el = document.getElementById('calendar_atv');
        var calendar_atv = new FullCalendar.Calendar(calendar_atv_el, {
          initialView: 'dayGridMonth',
          selectable: true,
          locale: 'pt-br',
          select: function(info){
            info["calendar"] = calendar_atv;
            let activity = modal_activity_fun(info);
            activity.assemble();
          },
          eventClick: function(info) {
            let activity_view = modal_activity_view_fun(info);
            activity_view.assemble();
          }
        });
        calendar_atv.render();
      });
}

function create_multiselect(element){
    element.multiselect({
      enableFiltering: true,
      includeSelectAllOption: true,
      enableCaseInsensitiveFiltering: true,
      buttonWidth: '100%',
      maxHeight: 450,
  });
}

(function() {

  // start fullcalendar
  fullcalendar_activities();

})();
.modalPdf{visibility: visible;}
.m-0 {margin: 0!important;}
.m-1 {margin: .25rem!important;}
.m-2 {margin: .5rem!important;}
.m-3 {margin: 1rem!important;}
.m-4 {margin: 1.5rem!important;}
.m-5 {margin: 3rem!important;}
.mr-0{margin-right: 0rem!important;text-align: justify;}
.mr-3{margin-right: 1rem!important;text-align: justify;}
.ml-0{margin-left: 0rem!important;text-align: justify;}
.ml-3{margin-left: 1rem!important;text-align: justify;}
.mt-0{margin-top: 0rem!important;text-align: justify;}
.mt-3{margin-top: 1rem!important;text-align: justify;}
.mr-2, .mx-2 {margin-right: .5rem!important;}
.mt-4, .my-4 {margin-top: 1.5rem!important;}
.mt-5{margin-top: 3rem!important;text-align: justify;}
.ml-auto, .mx-auto {margin-left: auto!important;}
.mr-auto, .mx-auto {margin-right: auto!important;}
.mx-3 {margin-right: 1rem!important;margin-left: 1rem!important;}
.mb-2, .my-2 {margin-bottom: .5rem!important;}
.mt-2, .my-2 {margin-top: .5rem!important;}
.mb-auto, .my-auto {margin-bottom: auto!important;}
.mt-auto, .my-auto {margin-top: auto!important;}
.ml-0, .mx-0 {margin-left: 0!important;}
.mr-0, .mx-0 {margin-right: 0!important;}
.ml-1, .mx-1 {margin-left: .25rem!important;}
.mr-1, .mx-1 {margin-right: .25rem!important;}
.ml-4, .mx-4 {margin-left: 1.5rem!important;}
.mb-5, .my-5 {margin-bottom: 3rem!important;}
.p-2 {padding: .5rem!important;}
.p-3 {padding: 1rem!important;}
.pl-0, .px-0 {padding-left: 0!important;}
.pr-0, .px-0 {padding-right: 0!important;}
.pb-2, .py-2 {padding-bottom: .5rem!important;}
.pt-2, .py-2 {padding-top: .5rem!important;}
.pl-2, .px-2 {padding-left: .5rem!important;}
.pr-2, .px-2 {padding-right: .5rem!important;}
.pl-3, .px-3 {padding-left: 1rem!important;}
.pr-3, .px-3 {padding-right: 1rem!important;}
.pl-5, .px-5 {padding-left: 3rem!important;}
.pr-5, .px-5 {padding-right: 3rem!important;}
.align-middle {vertical-align: middle!important;}
.align-items-center {
    -webkit-box-align: center!important;
    -ms-flex-align: center!important;
    align-items: center!important;
}
.d-flex {
    display: -webkit-box!important;
    display: -ms-flexbox!important;
    display: flex!important;
}
.h-100 {height: 100%!important;}
.btn {white-space:normal !important; word-wrap: break-word; word-break: normal;}
.form-row {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-wrap: wrap;
    flex-wrap: wrap;
    margin-right: -5px;
    margin-left: -5px;
}
.form-row>.col, .form-row>[class*=col-] {
    padding-right: 5px;
    padding-left: 5px;
}
.dropzone, .rounded {border-radius: .25rem!important;}
.dropzone{border-style:dashed;}
.dz-progress{top: 70%!important;}
.dz-error-message{top:105%!important;}
.table-responsive {
    display: block;
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    -ms-overflow-style: -ms-autohiding-scrollbar;
}
.ftacoes{white-space: nowrap;}
.a-remove{
    white-space: nowrap;
    font-size: 13px;
    text-align: center;
    display: block;
    cursor: pointer;
    border: none;
}
.disabledbutton {
    pointer-events: none;
    opacity: 0.4;
}
.header{
    position:sticky;
    top: 0;
}
.valid-tooltip {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 5;
    display: none;
    max-width: 100%;
    padding: .25rem .5rem;
    margin-top: .1rem;
    font-size: 1.4rem;
    line-height: 1.5;
    color: #fff;
    background-color: rgba(40,167,69,.9);
    border-radius: .25rem;
}
.invalid-tooltip {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 5;
    display: none;
    max-width: 100%;
    padding: .25rem .5rem;
    margin-top: .1rem;
    font-size: 1.4rem;
    line-height: 1.5;
    color: #fff;
    background-color: rgba(220,53,69,.9);
    border-radius: .25rem;
}
.bg-light {background-color: #f8f9fa!important;}
.d-table{ display: table!important; }
.position-relative {position: relative!important;}
.float-right {float: right!important;}
.btn-x-sm {
    padding: .25rem .5rem;
    font-size: .875rem;
    line-height: 1.5;
    border-radius: .2rem;
}
.align-middle {
    vertical-align: middle!important;
}
.cursor-pointer{
    cursor: pointer;
}
.btn-default2 {
    color: #333;
    background-color: #fff;
}
.btn-default2:focus {
    color: #333;
    background-color: #e6e6e6;
}
.btn-default2:hover {
    color: #333;
    background-color: #e6e6e6;
}
.btn-default2:active {
    color: #333;
    background-color: #e6e6e6;
}
@keyframes spinner-border {
    to { transform: rotate(360deg)}
}
.spinner-border {
display: inline-block;
width: 2rem;
height:  2rem;
vertical-align: text-bottom;
border: .25em solid currentColor;
border-right-color: transparent;
border-radius: 50%;
-webkit-animation: .75s linear infinite spinner-border;
animation: .75s linear infinite spinner-border;
}
.spinner-border-sm {
    width: 1rem;
    height: 1rem;
    border-width: .2em;
} 
.spinner-border-md {
    width: 1.5rem;
    height: 1.5rem;
    border-width: .25em;
}
.spanIcone{ width: 1.8rem;}
.fc-event{
    cursor: pointer;
}
.generic_focus:focus{
    border-color: #66afe9;
    outline: 0;
    -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102,175,233,.6);
    box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102,175,233,.6);
}
.text-truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
<!DOCTYPE html>
<html lang="pt-br">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="Content-Language" content="pt-br">
    <title>Atividades dos Colaboradores</title>

    <!-- jQuery -->
    <script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
    <!-- Bootstrap -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
    
    <!-- Ícones -->
    <script src="https://kit.fontawesome.com/a076d05399.js"></script>
    <!-- fullcalendar -->
    <script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.4.0/main.min.js" integrity="sha256-oenhI3DRqaPoTMAVBBzQUjOKPEdbdFFtTCNIosGwro0=" crossorigin="anonymous"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fullcalendar@5.4.0/main.min.css" integrity="sha256-uq9PNlMzB+1h01Ij9cx7zeE2OR2pLAfRw3uUUOOPKdA=" crossorigin="anonymous">
    <script src='https://cdn.jsdelivr.net/npm/rrule@2.6.4/dist/es5/rrule.min.js'></script>
    <!-- multiselect -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-multiselect/0.9.15/css/bootstrap-multiselect.css" integrity="sha512-EvvoSMXERW4Pe9LjDN9XDzHd66p8Z49gcrB7LCUplh0GcEHiV816gXGwIhir6PJiwl0ew8GFM2QaIg2TW02B9A==" crossorigin="anonymous" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-multiselect/0.9.15/js/bootstrap-multiselect.min.js" integrity="sha512-aFvi2oPv3NjnjQv1Y/hmKD7RNMendo4CZ2DwQqMWzoURKxcqAoktj0nNG4LU8m23+Ws9X5uVDD4OXLqpUVXD5Q==" crossorigin="anonymous"></script>
    <!--datapicker-->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/css/bootstrap-datepicker.css"  rel='stylesheet' type='text/css'>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/js/bootstrap-datepicker.js"></script>
      <!--tradução datepicker para pt-->
      <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/locales/bootstrap-datepicker.pt-BR.min.js"></script>
    <!-- moment js -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/locale/pt-br.min.js" integrity="sha512-1IpxmBdyZx3okPiZ14mzw6+pOGa690uDmcdjqvT310Kwv3NRcjvL/aOtoSprEyvkDdAb7ZtM2um6KrLqLOY97w==" crossorigin="anonymous"></script>
    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
      <script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
    <![endif]-->
  </head>
  <body>
    <div class="container">
        <div class="row">
            <div class="col-xs-12">
                <!--Painel que contém todo o conteúdo-->
                <div class="panel mt-3 panel-default">
                    <div class="panel-body">
                        <div id="calendar_atv"></div>
                    </div>
                </div><!-- /.painel -->
            </div><!-- /.col -->
        </div><!-- /.row -->
    </div><!-- /.container -->

    <div id="modal_activity" class="modal fade bs-example-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <h4 class="modal-title">New</h4>
          </div>
          <div class="modal-body">
            <form id="activity_form">
              <div class="form-group">
                <label for="activity_title" class="control-label">Title:</label>
                <input type="text" class="form-control" id="activity_title", placeholder="Adicione um título"  maxlength="40" required>
              </div>
              <div class="form-group">
                <label for="activity_description" class="control-label">Description:</label>
                <textarea class="form-control" rows="4" id="activity_description" placeholder="Descreva a atividade" required></textarea>
              </div>
              <div class="form-group">
                <label for="activity_from" class="control-label">for:</label>
                <select id="activity_from" name="multiselect[]" multiple="multiple" class="form-control">
                  <option valeu="1">email1@emal.com</option>
                  <option valeu="2">email2@emal.com</option>
                  <option valeu="3">email3@emal.com</option>
                </select>
              </div>
              <label for="activity_start_date" class="control-label">scheduling:</label>
              <div class="row">
                <div class="col-xs-6 pr-0">
                  <div class="form-group mx-0">
                    <label for="activity_start_date" class="col-xs-1 px-0 control-label"><i class="far fa-clock"  style="vertical-align: -6px;"></i></label>
                    <div class="col-xs-11 pl-1 pr-0">
                      <input type="text" class="form-control" id="activity_start_date" placeholder="data inicial" required>
                    </div>
                  </div>
                </div>
                <div class="col-xs-6">
                  <div class="form-group ">
                    <input type="text" class="form-control" id="activity_end_date" placeholder="data final" required>
                  </div>
                </div>
              </div>
              <div class="row">
                <div class="col-xs-6">
                  <div class="form-group mx-0">
                    <div class="col-xs-1 px-0"></div>
                    <div class="col-xs-8 pl-1 pr-0">
                      <select id="activity_repetition" name="activity_from"class="form-control" required>
                        <option value="1">does not repeat</option>
                        <option value="2">weekly</option>
                        <option value="3">monthly</option>
                      </select>
                    </div>
                  </div>
                </div>
              </div>
            </form>
          </div>
          <div class="modal-footer">
            <button id="add_activity" type="button" class="btn btn-primary" data-toggle="popover" data-trigger="manual" data-placement="top" data-content="Some fields are empty.">Save</button>
          </div>
        </div><!-- /.modal-content -->
      </div><!-- /.modal-dialog -->
    </div><!-- /.modal -->

    <div id="modal_activity_view" class="modal fade bs-example-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <h4 class="modal-title text-truncate">Evento</h4>
          </div>
          <div class="modal-body">
            <form id="activity_form_view">
              <div class="text-center" >Status: <span id="activity_status_view" style="vertical-align: 2px;" class="label label-default ">...</span></div>
              <h5>Description</h5>
              <div class="row">
                <div class="col-xs-12">
                  <div class="form-group mx-0">
                    <div class="col-xs-1 px-0">
                      <i class="fas fa-align-justify" aria-hidden="true"></i>
                    </div>
                    <div class="col-xs-11 pl-0 pr-0">
                      <p id="activity_description_view"></p>
                    </div>
                  </div>
                </div>
              </div>
              <h5 >Scheduling</h5>
              <div class="row">
                <div class="col-xs-12">
                  <div class="form-group mx-0">
                    <div class="col-xs-1 px-0">
                      <i class="far fa-calendar-alt" aria-hidden="true"></i>
                    </div>
                    <div class="col-xs-11 pl-0 pr-0">
                      <p id="activity_schedule_view"></p>
                      <p id="activity_repetition_view"></p>
                    </div>
                  </div>
                </div>
              </div>
              <div class="text-center">
                <button type="button" class="mt-5 form-check btn btn-default">
                  <i class="fa fa-check mr-2" aria-hidden="true"></i>Mark as done
                </button>
              </div> 
            </form>
          </div>
        </div><!-- /.modal-content -->
      </div><!-- /.modal-dialog -->
    </div><!-- /.modal -->
  </body>
  <link rel="stylesheet" href="activities.css">
  <script src="activities.js"></script>
</html>

basically when the period is selected in the calendar, a modal is opened in which the user must enter information such as: title, description and the repetition options for the event.

I tried to use "dow:" when creating the event, but when it is a long event (with more than one day), it divides that event into days. I also tried to use "repeat: 1", but nothing just happened

ADyson
  • 57,178
  • 14
  • 51
  • 63
Cristiano Felipe
  • 117
  • 1
  • 10
  • That question you referred to is for a very old version of fullCalendar. If you just look in the documentation for v5 you'll find that recurring events are supported directly: https://fullcalendar.io/docs/recurring-events – ADyson Dec 18 '20 at 16:03
  • @ADyson but this don't show a way to repeat monthy – Cristiano Felipe Dec 18 '20 at 20:50
  • Did you read on as far as the part about RRule? – ADyson Dec 18 '20 at 20:55

0 Answers0