Search code examples
javascriptfullcalendardom-eventsfullcalendar-4

FullCalendar v4 - How to show events on the calendar with a form?


I am unable to dynamically add events with a bootstrap modal / form. I manage to catch the click on any date and the modal opens. I complete the inputs but I can't get them to show on calendar. I get the values ​​of the inputs and save them in variables to pass them to the calendar with addEvent but I can't. I'm starting with programming, help is appreciated!

bis I am unable to dynamically add the events with a bootstrap modal / form. I manage to catch the click on any date and the modal opens. I complete the inputs but I can't get them to show on calendar. I get the values ​​of the inputs and save them in variables to pass them to the calendar with addEvent but I can't. I'm starting with programming, help is appreciated!

Here the FullCalendar and Js

// VARIABLES
    // Leen el valor de cada campo del formulario
    let titulo = document.querySelector("#titulo").value    
    let descripcion = document.querySelector("#descripcion").value
    let fecha = document.querySelector("#fecha").value
    let hora = document.querySelector("#hora").value
    let color = document.querySelector("#color").value
    // Submit formulario
    let enviar = document.querySelector("#btnAgregar") 

  // FULLCALENDAR
  document.addEventListener('DOMContentLoaded', function () {
    let calendarEl = document.getElementById('calendar');

    let calendar = new FullCalendar.Calendar(calendarEl, {
      locale: "es",
      plugins: ["interaction", "dayGrid", "timeGrid"],
      selectable: true,
      defaultView: "timeGridWeek",
      header: {
        left: "prev,next today",
        center: "title",
        right: "timeGridDay,timeGridWeek,dayGridMonth",
      },

      // Selecciona con click en una fecha/hora determinada
      dateClick: function () {

        // Acciona el modal
        $("#modalEventos").modal()

        // EVENT LISTENER
        enviar.addEventListener("submit", enviarEvento)

        // FUNCIONES
        function enviarEvento() {
          calendar.addEvent({    // https://fullcalendar.io/docs/event-model
            title: titulo,
            description: descripcion,
            start: fecha,   // dateStr  
            hora: hora,   // 'T00:00:00'
            color: color
          })
          //Cierra el modal
          $('#modalEventos').modal('toggle'); // hide
        }
      },

    });
    calendar.render();
  });

This is the HTML of the form I use:

<!-- Modal -->
        <div class="modal fade" id="modalEventos" data-backdrop="static" data-keyboard="false" tabindex="-1" role="dialog"
            aria-labelledby="staticBackdropLabel" aria-hidden="true">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title" id="tituloEvento">Agregar Evento</h5>
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                    </div>
                    <form action="#" id="guardar">
                        <div class="modal-body">
                            <div class="form-group row" id="elTitulo">
                                <label for="titulo" class="col-sm-2 col-form-label">Titulo</label>
                                <div class="col-sm-10">
                                    <input type="text" class="form-control" id="titulo">
                                </div>
                            </div>

                            <div class="form-group row">
                                <label for="descripcion" class="col-sm-2 col-form-label">Descripción</label>
                                <div class="col-sm-10">
                                    <textarea class="form-control" id="descripcion" rows="2"></textarea>
                                </div>
                            </div>
                            <div class="form-group row">
                                <label for="fecha" class="col-sm-2 col-form-label">Fecha</label>
                                <div class="col-sm-10">
                                    <input type="text" class="form-control" id="fecha" value="">
                                </div>
                            </div>
                            <div class="form-group row">
                                <label for="hora" class="col-sm-2 col-form-label">Horario</label>
                                <div class="col-sm-10">
                                    <input type="text" class="form-control" id="hora">
                                </div>
                            </div>
                            <div class="form-group row">
                                <label for="color" class="col-sm-2 col-form-label">Color</label>
                                <div class="col-sm-3">
                                    <input type="color" class="form-control" id="color" value="#3788d8">
                                    </select>
                                </div>
                            </div>
                        </div>
                        <div class="modal-footer">
                            <button type="submit" class="btn btn-primary" id="btnAgregar">Agregar</button>
                            <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancelar</button>
                        </div>
                    </form>
                </div>
            </div>
        </div>

Solution

  • I can see two problems - one which is definitely an issue and another which probably is (although I haven't tested it):

    1) What's definitely a problem is the way you're getting values from the inputs in the modal. Your code gets those values when the page first loads, and puts them into variables. But, since this occurs when the page loads, it means this is before the user has had any chance to type anything into them! You then keep these variables until you try to add it to the calendar. You need to wait until the user has clicked on the submit button before you try to see what they typed.

    2) Your function enviarEvento and its associated event listener are declared inside the "dateClick" callback, which means a new version of that function and listenern will be declared every time someone clicks. That isn't necessary, and although I haven't tested, there's also a chance it could behave in unexpected ways to do the way JavaScript deals with closures - e.g. you might find it re-adds all previously added events every time you click, due to the build-up of event handlers. You can just move these outside the calendar declaration.

    Here's a fixed version:

    // FULLCALENDAR
    document.addEventListener('DOMContentLoaded', function () {
      // Submit formulario
      let enviar = document.querySelector("#btnAgregar");
      let calendarEl = document.getElementById('calendar');
    
      let calendar = new FullCalendar.Calendar(calendarEl, {
        locale: "es",
        plugins: ["interaction", "dayGrid", "timeGrid"],
        selectable: true,
        defaultView: "timeGridWeek",
        header: {
          left: "prev,next today",
          center: "title",
          right: "timeGridDay,timeGridWeek,dayGridMonth",
        },
    
        // Selecciona con click en una fecha/hora determinada
        dateClick: function () {
    
          // Acciona el modal
          $("#modalEventos").modal();
        },
      });
    
      calendar.render();
    
      // EVENT LISTENER
      enviar.addEventListener("submit", enviarEvento)
    
      // FUNCIONES
      function enviarEvento() {
    
        let titulo = document.querySelector("#titulo").value;
        let descripcion = document.querySelector("#descripcion").value;
        let fecha = document.querySelector("#fecha").value;
        let hora = document.querySelector("#hora").value;
        let color = document.querySelector("#color").value;
    
        calendar.addEvent({    // https://fullcalendar.io/docs/event-model
          title: titulo,
          description: descripcion,
          start: fecha,   // dateStr  
          hora: hora,   // 'T00:00:00'
          color: color
        });
    
        //Cierra el modal
        $('#modalEventos').modal('toggle'); // hide
      }
    });
    

    Also some advice:

    1) the dateClick function will tell you the day which was clicked on, but you're ignoring that incoming value. You could use that to pre-populate the "start" field in your modal so the user doesn't have to type it. See https://fullcalendar.io/docs/dateClick

    2) Even better, if you switch from using the dateClick to the select callback, then when you're using the "timeGrid" or "timeline" views, it will allow the user to drag and drop (or just click) to select a specific period of time, and then tell you the start and end dates & times which they selected - again you can use this to pre-populate a form and make it more user-friendly. See https://fullcalendar.io/docs/select-callback