Cómo repetir eventos en fullcalendar

Quiero saber cómo repetir eventos de fechas variables (horas de inicio y final), semanal y mensual.

Encontré esta respuesta, pero no funcionó para mí: Repetir eventos completos diariamente, mensual y anual

Este es mi código:

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, "\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;
}
html

  
    
    
    
    Atividades dos Colaboradores

     jQuery 
    
     Bootstrap 
    
    
    
     Ícones 
    
     fullcalendar 
    
    [email protected]/main.min.css" integrity="sha256-uq9PNlMzB+1h01Ij9cx7zeE2OR2pLAfRw3uUUOOPKdA=" crossorigin="anonymous">
    
     multiselect 
    
    
    datapicker
    
    
      tradução datepicker para pt
      
     moment js 
    
    
     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]>
      
      
    
  
    
Painel que contém todo o conteúdo
/.painel
/.col
/.row
/.container /.modal /.modal

Básicamente cuando el período se selecciona en el calendario, se abre un modal en el que el usuario debe introducir información como: título, descripción y las opciones de repetición para el evento.

Intenté utilizar "hacer:" al crear el evento, pero cuando es un evento largo (con más de un día), divide ese evento en días. También intenté usar "repeat: 1", pero no pasó nada.

Pregunta hecha hace 3 años, 4 meses, 28 días - Por pixelpilot


2 Respuestas:

  • Para repetir eventos en fullcalendar con fechas variables y opciones de repetición como semanal y mensual, puedes implementar la funcionalidad de repetición utilizando la librería RRule.js.

    Aquí te muestro cómo puedes modificar tu código para incorporar la funcionalidad de repetición:

    • Asegúrate de incluir la librería RRule.js en tu código HTML:
    html
    
    
    • En tu función `add_activity()`, puedes crear reglas de repetición utilizando RRule.js y añadir esas reglas al evento creado:
    javascript
    if(total_empty == 0){
        let startStr = moment($('activity_start_date').datepicker('getDate')).format('YYYY-MM-DD');    let endStr = moment($('activity_end_date').datepicker('getDate')).format('YYYY-MM-DD');    
        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 rrule;
        let repetition = form.find('activity_repetition').val();
        if(repetition == 2){
            rrule = new RRule({
                freq: RRule.WEEKLY,
                dtstart: new Date(startStr),
                until: new Date(endStr)
            });
        } else if(repetition == 3){
            rrule = new RRule({
                freq: RRule.MONTHLY,
                dtstart: new Date(startStr),
                until: new Date(endStr)
            });
        }
    
        let event_object = {
            title: title,
            start: startStr,
            end: endStr,
            allDay: true,
            rrule: rrule.toString(),
            extendedProps: extendedProps
        };
    
        info.calendar.addEvent(event_object);
    
        modal_activity.modal('hide');
    }
    

    En este código, se crea una regla de repetición ya sea semanal o mensual dependiendo de la opción seleccioanda en el formulario. Luego, se agrega esa regla al evento creado.

    Con estos cambios, deberías poder repetir eventos según el intervalo seleccionado por el usuario. No olvides ajustar y probar el código según tus necesidades específicas.

    Respondida el Dec 18, 2020 a las 16:43 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El problema puede deberse a que los eventos se están creando con la propiedad repeat: 1, que especifica que el evento se repetirá una vez. Para que el evento se repita semanal o mensualmente, debes usar la propiedad rrule con la configuración de recurrencia adecuada.

    Aquí tienes un ejemplo de cómo puedes crear eventos semanales o mensuales utilizando la propiedad rrule:

    
    let event_object = {
      title: title,
      start: startStr,
      end:endStr,
      allDay: true,
      extendedProps: {
        description: form.find('activity_description').val(),    from: form.find('activity_from').val(),    repetition:  form.find('activity_repetition option:selected' ).text(),    status: "Scheduled",
      }
    };
    
    let repetition = form.find('activity_repetition').val();
    if (repetition == 3) {
      event_object['rrule'] = {
        freq: 'monthly',
        interval: 1,
      };
    }
    if (repetition == 2) {
      event_object['rrule'] = {
        freq: 'weekly',
        interval: 1,
      };
    }
    

    Los siguientes recursos pueden resultarte útiles para obtener más información sobre el uso de rrule:

    Documentación de FullCalendar sobre rrule Reglas de recurrencia de RRule

    También, asegúrate de que tu versión de FullCalendar es compatible con la propiedad rrule.

    Respondida el Dec 18, 2020 a las 16:53 - por Gemini

    Votos positivos: 0 | Votos negativos: 0