0

Im having problem with yii2fullcalendar eventDrop. I’ve made a JsExpression for eventDrop and eventRender as seen below.

The problem is, when I drag and drop an event to a different day and refresh the page, it loses it’s color, and description goes to undefined.

With eventRender I add color and description properties to event class.

I tried modifying fullcalendar.css and fullcalendar.min.css .fc-event with no success

Here's the code

<?php
            $JsEventRender = 'function(event, element) {
                element.addClass(event.description);
                element.addClass(event.color);
            }'
        ?>

<?php
            $JsEventDrop = 'function(event, delta, revertFunc) {
                    var event_data = {
                        id: event.id,
                        titulo: event.title,
                        descripcion: event.description,
                        fecha_inicio: $.fullCalendar.formatDate(event.start, "YYYY-MM-DD"),
                        hora_inicio: $.fullCalendar.formatDate(event.start, "HH:mm"),
                        hora_termino: $.fullCalendar.formatDate(event.end, "HH:mm"),
                        fecha_termino: $.fullCalendar.formatDate(event.end, "YYYY-MM-DD"),
                        color: event.color,
                    };
                    if (!confirm("¿Está seguro que desea modificar la fecha y/o hora?")) {
                        revertFunc();
                    }
                    else {
                        $.ajax({
                            type: "POST",
                            url: "index.php?r=calendario/update" + "&id=" + event_data.id 
                            + "&titulo=" + event_data.titulo + "&descripcion=" + event_data.description
                            + "&fecha_inicio=" + event_data.fecha_inicio + "&hora_inicio=" + event_data.hora_inicio 
                            + "&hora_termino=" + event_data.hora_termino + "&fecha_termino=" + event_data.fecha_termino
                            + "&color=" + event_data.color,
                            success: function(json) {
                                alert("Fecha y/o hora modificada correctamente");
                            }
                        });

                    }
                }'
        ?>

<?= yii2fullcalendar\yii2fullcalendar::widget([
            'events' => $events,
            'id' => 'calendar',
            'options' => [
                      'lang' => 'es',
                    ],
            'clientOptions' => [
                    'selectable' => false,
                    'editable' => true,
                    'droppable' => true,
                    'header' => [
                        'left' => 'prev,next,today',
                        'center' => 'title',
                        'right' => 'month,agendaWeek,agendaDay,listDay',
                        ],
                'minTime' => '08:00',
                'maxTime' => '21:00',
                'height' => 'auto',
                'snapDuration' => '00:05:00',
                'eventRender' => new JsExpression($JsEventRender),
                'eventClick' => new JsExpression($JsEventClick),
                'eventDrop' => new JsExpression($JsEventDrop),
                'eventResize' => new JsExpression($JsEventResize),
                    ],
            ]);
        ?>

<?php
public function actionCreate($fecha_inicio, $fecha_termino)
    {   
        $model = new Calendario();
        $model->fecha_inicio = $fecha_inicio;
        $model->fecha_termino = $fecha_termino;
        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            return $this->redirect(['index']);
        }

        return $this->renderAjax('create', [
            'model' => $model,
        ]);
    }

public function actionUpdate($id, $titulo, $descripcion, $fecha_inicio, $hora_inicio, $hora_termino, $fecha_termino, $color)
    {
        $model = $this->findModel($id);
        $model->id = $id;
        $model->titulo = $titulo;
        $model->descripcion = $descripcion;
        $model->fecha_inicio = $fecha_inicio;
        $model->hora_inicio = $hora_inicio;
        $model->hora_termino = $hora_termino;
        $model->fecha_termino = $fecha_termino;
        $model->color = $color;
        $model->save();

        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            return $this->redirect(['index']);
        }

        return $this->renderAjax('update', [
            'model' => $model,
        ]);
    }

At first I thought it was an Url problem but it is not. I've posted same issue in Yii Framework's Forum https://forum.yiiframework.com/t/fullcalendar-eventdrop-removes-event-color-and-event-description/125790

  • You need to use `eventSources` option rather than `events` to load and reload events, and you need to update them once you drag or drop them to a new timeline so that the color and other properties are updated before they are loaded again, are you saving the events in your datatabase and loading them from there, what does the `$events` hold and how is it populated. and the `description` is deprecated now, which version are you using – Reborn Apr 20 '19 at 14:09
  • Yes, I am saving events in controller's actionUpdate with $model->save() and loading them from db in actionIndex with find()->all() as well. $events is an array and it is populated with a foreach. I'm using FullCalendar v3.9.0 – jc.reyes.suazo Apr 22 '19 at 00:27
  • you are using `events` option which uses preloaded array whereas you should use `eventSources` which sends an ajax call to a single/multiple action(s) where you return the events, and you should save the `backgroundColor` too along with other properties, this way you would save and call the sources again after saving so that the new background color is saved and loaded respecitively, i have previously added an [Answer](https://stackoverflow.com/questions/52076369/yii2-full-calendar-event-filtering-not-working/52214627#52214627) describing the usage of `eventSourcces` which can help you out. – Reborn Apr 22 '19 at 00:34
  • implement using that answer and if you run into issues you can update your question, so a complete list of properties supported by fullcalendar event model see here https://fullcalendar.io/docs/event-object – Reborn Apr 22 '19 at 00:36
  • I've read the answer you provided and I think I understand a little bit of how things work. I believe eventSources will get the event properties I save with actionCreate and ActionUpdate, but how? Im currently renderingAjax and sending $model on both actions. I edited the question to show you the controller actions. Can you give me an example? – jc.reyes.suazo Apr 23 '19 at 02:36
  • if you are calling the update action when you drag an event in the calendar and drop it on a new place, then you just need to configure the `eventSources` option and where you send ajax call to update the event you should call the `$('#eventFilterCalendar').fullCalendar('refetchEvents');` method to re-populate the events in the calendar with new properties loaded, you dont have to change the `eventSources` url every time as in that question i refferred you to look into – Reborn Apr 23 '19 at 18:39
  • can you mark the answer as correct if it worked for you? – Reborn May 08 '19 at 19:06
  • I thank you for your quick response and apologise for the delay. I achieved this in a different way weeks ago. Read my answer. – jc.reyes.suazo May 10 '19 at 08:08

2 Answers2

0

To Do

As per discussion you need to use eventSources to dynamically load events and then re-fetch the events once they are updated.

How To

A major part can be covered from a previous answer I wrote earlier, which describes in detail how to use the eventSources option, so I will not go into those details. the only thing that differs from that answer is that you have to re-fetch the events when you drag & drop an event on the calendar and for that you are already using the option eventDrop where you are getting the event properties and sending an ajax call to update the event properties in the database, so all you need is to add

  • Create an action in your controller which returns the events list in the format described in the previous answer I mentioned.
  • List the url of that action in the eventSources option that takes an array of urls like ['/controller/action'].
  • Refetch the events once you update the event by calling refetchEvents method like below.

    $('#calendar').fullCalendar('refetchEvents');
    

    and this needs to be the last line of the script that you have for the eventDrop, so your complete code for the javascript will look like

     $JsEventDrop = 'function(event, delta, revertFunc) {
                    var event_data = {
                        id: event.id,
                        titulo: event.title,
                        descripcion: event.description,
                        fecha_inicio: $.fullCalendar.formatDate(event.start, "YYYY-MM-DD"),
                        hora_inicio: $.fullCalendar.formatDate(event.start, "HH:mm"),
                        hora_termino: $.fullCalendar.formatDate(event.end, "HH:mm"),
                        fecha_termino: $.fullCalendar.formatDate(event.end, "YYYY-MM-DD"),
                        color: event.color,
                    };
                    if (!confirm("¿Está seguro que desea modificar la fecha y/o hora?")) {
                        revertFunc();
                    }
                    else {
                        $.ajax({
                            type: "POST",
                            url: "index.php?r=calendario/update" + "&id=" + event_data.id 
                            + "&titulo=" + event_data.titulo + "&descripcion=" + event_data.description
                            + "&fecha_inicio=" + event_data.fecha_inicio + "&hora_inicio=" + event_data.hora_inicio 
                            + "&hora_termino=" + event_data.hora_termino + "&fecha_termino=" + event_data.fecha_termino
                            + "&color=" + event_data.color,
                            success: function(json) {
                                alert("Fecha y/o hora modificada correctamente");
                            }
                        });
    
                    }
    
                //this line will refetch the events on the calendar with the newly saved values
                $("#calendar").fullCalendar("refetchEvents");
                }'
    
Reborn
  • 19,713
  • 8
  • 36
  • 61
0

I solved this by changing actionUpdate to it's default, and adding 2 new actions called actionUpdateDrop and actionUpdateResize, one for each of the JsExpressions, JsEventDrop and JsEventResize respectively. I discovered that eventRender doesn't work at all so I deleted it. I also changed JsExpressions to call these actions without passing tittle, description, and color because these parameters are not needed in the update. And magically events now keeps it's description and color.

//CalendarioController.php

public function actionUpdate($id)
    {
        $model = $this->findModel($id);

        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            return $this->redirect(['index']);
        }

        return $this->renderAjax('update', [
            'model' => $model,
        ]);
    }

    public function actionUpdateDrop($id, $fecha_inicio, $hora_inicio, $hora_termino, $fecha_termino)
    {
        $model = $this->findModel($id);
        $model->fecha_inicio = $fecha_inicio;
        $model->hora_inicio = $hora_inicio;
        $model->hora_termino = $hora_termino;
        $model->fecha_termino = $fecha_termino;
        $model->save();

        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            return $this->redirect(['index']);
        }

        return $this->render('update', [
            'model' => $model,
        ]);
    }

    public function actionUpdateResize($id, $hora_inicio, $hora_termino)
    {
        $model = $this->findModel($id);
        $model->hora_inicio = $hora_inicio;
        $model->hora_termino = $hora_termino;
        $model->save();

        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            return $this->redirect(['index']);
        }

        return $this->render('update', [
            'model' => $model,
        ]);
    }

//Index.php

<p>
        <?php
            $JsEventDrop = 'function(event, delta, revertFunc) {
                    var event_data = {
                        id: event.id,
                        fecha_inicio: $.fullCalendar.formatDate(event.start, "YYYY-MM-DD"),
                        hora_inicio: $.fullCalendar.formatDate(event.start, "HH:mm"),
                        hora_termino: $.fullCalendar.formatDate(event.end, "HH:mm"),
                        fecha_termino: $.fullCalendar.formatDate(event.end, "YYYY-MM-DD"),
                    };
                    if (!confirm("¿Está seguro que desea modificar la fecha y/o hora?")) {
                        revertFunc();
                    }
                    else {
                        $.ajax({
                            type: "POST",
                            url: "index.php?r=calendario/update-drop" + "&id=" + event_data.id 
                            + "&fecha_inicio=" + event_data.fecha_inicio + "&hora_inicio=" + event_data.hora_inicio 
                            + "&hora_termino=" + event_data.hora_termino + "&fecha_termino=" + event_data.fecha_termino,
                            success: function(json) {
                                alert("Fecha y/o hora modificada correctamente");
                            }
                        });

                    }
                }'
        ?>
    </p>

    <p>
        <?php
            $JsEventResize = 'function(event, delta, revertFunc) {
                    var event_data = {
                        id: event.id,
                        hora_inicio: $.fullCalendar.formatDate(event.start, "HH:mm"),
                        hora_termino: $.fullCalendar.formatDate(event.end, "HH:mm"),
                    };
                    if (!confirm("¿Está seguro que desea modificar la hora?")) {
                        revertFunc();
                    }
                    else {
                        $.ajax({
                            type: "POST",
                            url: "index.php?r=calendario/update-resize" + "&id=" + event_data.id 
                            + "&hora_inicio=" + event_data.hora_inicio + "&hora_termino=" + event_data.hora_termino,
                            success: function(json) {
                                alert("Hora modificada correctamente");
                            }
                        });
                    }
               }'
         ?>
   </p>