Partage
  • Partager sur Facebook
  • Partager sur Twitter

[SF 4.4] Draggable External Event Fullcalendar v4

Sujet résolu
    6 avril 2020 à 10:34:14

    Bonjour,

    J'essaie en vain de sauvegarder en base les évenements externe ajouter au calendrier sur fullcalendar v4.

    Mon problème est que lorsque un événement est ajouté sur le calendrier la date de début et de fin ainsi que le titre sont marqué comme "undefined"

    Du coups à l'ajout d'un événement j'obtiens l'érreur :

    TypeError: info.start is undefined



    Ma vue :

    		<link href="{{ asset('plugins/fullcalendar/core/main.min.css') }}" rel="stylesheet" />
    		<link href="{{ asset('plugins/fullcalendar/daygrid/main.min.css') }}" rel="stylesheet" />
    		<link href="{{ asset('plugins/fullcalendar/timegrid/main.min.css') }}" rel="stylesheet" />
    		<link href="{{ asset('plugins/fullcalendar/list/main.min.css') }}" rel="stylesheet" />
    		<style>
    		#external-events .fc-event {
    			margin: 10px 0;
    			cursor: pointer;
    		}
    
    		#calendar {
    			width: 100%;
    		}
    
    		.fc-event {
    		font-size: 1em;
    		border-radius: 2px;
    		border: none;
    		padding: 5px;
    		}
    
    		.fc-day-grid-event .fc-content {
    		color: #fff;
    		}
    
    		.fc-button {
    		background: #eaeaea;
    		border: none;
    		color: #666b6f;
    		margin: 0 3px !important;
    		padding: 5px 12px !important;
    		text-transform: capitalize;
    		height: auto !important;
    		box-shadow: none !important;
    		border-radius: 3px !important;
    		}
    
    		.fc-state-down, .fc-state-active, .fc-state-disabled {
    		background-color: #009ffc !important;
    		color: #ffffff !important;
    		text-shadow: none !important;
    		}
    
    		.fc-toolbar h2 {
    		font-size: 20px;
    		font-weight: 600;
    		line-height: 28px;
    		text-transform: uppercase;
    		}
    
    		.fc th.fc-widget-header {
    		background: #e6e6e6;
    		font-size: 13px;
    		text-transform: uppercase;
    		line-height: 18px;
    		padding: 10px 0px;
    		}
    
    		.fc-unthemed th, .fc-unthemed td, .fc-unthemed thead, .fc-unthemed tbody, .fc-unthemed .fc-divider, .fc-unthemed .fc-row, .fc-unthemed .fc-popover {
    		border-color: #eff1f3;
    		}
    		</style>
    
    
    
    		<div class="col-xs-12 col-md-8 col-lg-8 col-xl-9">
    				<div class="card-box tilebox-one noradius">
    						<div id="calendar"></div>
    
    				</div>
    		</div>
    
    <script src="{{ asset('js/jquery-ui.min.js') }}"></script>
    <script src="{{ asset('plugins/fullcalendar/core/locales/fr.js') }}"></script>
    
    <script src="{{ asset('plugins/fullcalendar/core/main.js') }}"></script>
    <script src="{{ asset('plugins/fullcalendar/daygrid/main.js') }}"></script>
    <script src="{{ asset('plugins/fullcalendar/list/main.js') }}"></script>
    <script src="{{ asset('plugins/fullcalendar/interaction/main.js') }}"></script>
    <script src="{{ asset('plugins/fullcalendar/timegrid/main.js') }}"></script>
    <script>
    
    
    			document.addEventListener('DOMContentLoaded', function() {
    			  var Calendar = FullCalendar.Calendar;
    			  var Draggable = FullCalendarInteraction.Draggable;
    
    			  var containerEl = document.getElementById('external-events');
    			  var calendarEl = document.getElementById('calendar');
    			  var checkbox = document.getElementById('drop-remove');
    
    			  // initialize the external events
    			  // -----------------------------------------------------------------
    
    			  new Draggable(containerEl, {
    			    itemSelector: '.fc-event',
    			    eventData: function(eventEl) {
    			      return {
    			        title: eventEl.innerText,
                	create: true,
        					duration: '08:00'
    			      };
    			    }
    			  });
    
    
    			  // initialize the calendar
    			  // -----------------------------------------------------------------
    
    			  var calendar = new Calendar(calendarEl, {
    			    plugins: [ 'interaction', 'dayGrid', 'timeGrid' ],
    			    header: {
    			      left: 'prev,next today',
    			      center: 'title',
    			      right: 'dayGridMonth,timeGridWeek,timeGridDay'
    			    },
    			    editable: true,
    					locale: 'fr',
    					events: [
    						{% for event in events %}
    							{
    								title          : '{{ event.title }}',
    								start          : '{{ event.start|date("Y-m-d h:i") }}',
    								end            : '{{ event.end|date("Y-m-d h:i") }}',
    								backgroundColor: '{{ event.color }}',
    							},
    						{% endfor %}
    
    					],
    					lazyFetching: true,
    					firstDay: 1,
    					selectable: true,
    					/*timeFormat: {
    							agenda: 'h:mmt',
    							'': 'h:mmt'
    					},*/
    					editable: true,
    					eventDurationEditable: true,
    					eventDrop: function(event){
    	            console.log("Entrée dans : eventDrop");
    	            console.log(event);
    	            var start1 = event.start.format("YYYY-MM-DD HH:mm:ss");
    	            var end1 = event.end.format("YYYY-MM-DD HH:mm:ss");
    
    	            var xhr = $.ajax({
    
    	                {# url: '{{ path('cli_planning_calendar_ajout', {'id': 'event.id' }) }}', #}
    	                data: 'action=update&title=' + event.title+'&start=' + start1 +'&end=' + end1 + '&id=' + event.id ,
    	                type: "POST",
    	                success: function(data) {
    	                    console.log(data);
    	                    window.location.reload(true);
    	                    //alert(json);
    	                },
    	                error: function() {
    	                    alert("erreur lors de l'appel de l'url dans POST event/drop : contactez l'administrateur du site");
    	                },
    	            });
    	        },
    
    
    			    defaultView: 'timeGridWeek',
    			    droppable: true, // this allows things to be dropped onto the calendar
    			    drop: function(info) {
    	            var start = info.start.format("YYYY-MM-DD HH:mm:ss");
    	            var end = info.end.format("YYYY-MM-DD HH:mm:ss");
    
    							var xhr = $.ajax({
    
    									url: '{{ path('cli_planning_calendar_ajout', {'id': idSalarie }) }}',
    									data: 'action=update&title=' + info.title+'&start=' + start +'&end=' + end + '&id=' + info.id ,
    									type: "POST",
    									success: function(data) {
    											console.log(data);
    											window.location.reload(true);
    											//alert(json);
    									},
    									error: function() {
    											alert("erreur lors de l'appel de l'url dans POST event/drop : contactez l'administrateur du site");
    									},
    							});
    			      // is the "remove after drop" checkbox checked?
    			      if (checkbox.checked) {
    			        // if so, remove the element from the "Draggable Events" list
    			        info.draggedEl.parentNode.removeChild(info.draggedEl);
    			      }
    			    }
    			  });
    
    			  calendar.render();
    			});
    </script>
    


    Mon controller :

    <?php
    
    namespace App\Controller\Client\Planning;
    
    use App\Entity\Client\Utilisateur;
    use App\Entity\Client\Planning\Event;
    use App\Entity\Client\Planning\Tache;
    use App\Form\Client\Planning\Tache\Type\AddType;
    use App\Form\Client\Planning\Event\Type\AddType as EventType;
    
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\Routing\Annotation\Route;
    use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
    
    class CalendarController extends AbstractController
    {
        /**
         * @Route("/client/planning", name="cli_planning_calendar")
         */
        public function voirPlanning(Request $request)
        {
            $user = $this->getUser();
            $salaries = $user->getSalaries();
            $events = $this->getDoctrine()->getRepository(Event::class)->findAll();
            $taches = $this->getDoctrine()->getRepository(Tache::class)->findByClient($user->getClient());
    
            $tache = new Tache();
            $form = $this->createForm(AddType::class, $tache);
            $form->handleRequest($request);
            if ($form->isSubmitted() && $form->isValid()) {
                $tache->setClient($user->getClient()->getId());
                $em = $this->getDoctrine()->getManager();
                $em->persist($tache);
                $em->flush();
                $this->addFlash(
                'notice',
                'Job ajouté'
                );
                return $this->redirectToRoute('cli_planning_calendar');
            }
            return $this->render('client/planning/calendar.html.twig', array(
                'salaries' => $salaries,
                'events' => $events,
                'taches' => $taches,
                'form' => $form->createView(),
            ));
        }
    
        /**
         * @Route("/client/salaries/{id}/planning", name="cli_salaries_planning_calendar")
         */
        public function voirPlanningSalaries(Request $request, $id)
        {
            $user = $this->getUser();
            $salaries = $user->getSalaries();
            $events = $this->getDoctrine()->getRepository(Event::class)->findAll();
            $taches = $this->getDoctrine()->getRepository(Tache::class)->findByClient($user->getClient());
    
            $tache = new Tache();
            $form = $this->createForm(AddType::class, $tache);
            $form->handleRequest($request);
            if ($form->isSubmitted() && $form->isValid()) {
                $tache->setClient($user->getClient()->getId());
                $em = $this->getDoctrine()->getManager();
                $em->persist($tache);
                $em->flush();
                $this->addFlash(
                'notice',
                'Job ajouté'
                );
                return $this->redirectToRoute('cli_planning_calendar');
            }
    
    
            $salarie = $user->getSalaries($id);
            $event = new Event;
    
            return $this->render('client/planning/calendar.html.twig', array(
                'salaries' => $salaries,
                'taches' => $taches,
                'events' => $events,
                'idSalarie' => $id,
                'form' => $form->createView(),
            ));
        }
    
            /**
             * @param Request $request
             * @Route("/client/salaries/{id}/planning/ajout", name="cli_planning_calendar_ajout")
             */
            public function dropEvent(Request $request, $id)
            {
              if ($request->isXmlHttpRequest())
              {
    
                $idEvent = $request->get('id');
                $title = $request->get('title');
                $startDate = $request->get('start');
                $endDate = $request->get('end');
    
                $em = $this->getDoctrine()->getManager();
                $rst = $em->getRepository(Event::class)->dropEvent($idEvent,$startDate,$endDate,$title);
    
              }
    
                return new Response("Erreur.");
            }
    
    }

    Mon repository :

    <?php
    
    namespace App\Repository\Client\Planning;
    
    use App\Entity\Client\Planning\Event;
    use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
    use Doctrine\Common\Persistence\ManagerRegistry;
    
    /**
     * @method Index|null find($id, $lockMode = null, $lockVersion = null)
     * @method Index|null findOneBy(array $criteria, array $orderBy = null)
     * @method Index[]    findAll()
     * @method Index[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
     */
    class EventRepository extends ServiceEntityRepository
    {
        public function __construct(ManagerRegistry $registry)
        {
            parent::__construct($registry, Event::class);
        }
    
        public function dropEvent($idEvent, $startDate, $endDate, $title)
        {
            return $this
                ->createQueryBuilder('e')
                ->update(Event::class, 'e')
                ->set('e.title', $title)
                ->set('e.start', $startDate)
                ->set('e.end', $endDate)
                ->where('e.id = id')
                ->setParameter('id', $idEvent)
                ->getQuery()
                ->getResult();
        }
    }
    



    Cela vas faire plus d'une semaine que je cherches en vain j'ai testé plusieurs méthodes aucune n'a fonctionner si quelqu'un a une idée cela serais grandement apprécier

    -
    Edité par TuxZero 6 avril 2020 à 10:38:36

    • Partager sur Facebook
    • Partager sur Twitter
      6 avril 2020 à 12:16:43

      Bonjour,

      J'utilise full calendar avec Symfony.

      1) je suppose que tu as bien vérifié que tes variables côté js étaient bien valorisées.

      2) je ne fais pas comme toi  :

      - je ne transmet pas directement un paramètre dans la route.

      - je transmets trous les paramètres dans le data.

      je te donne mon exemple :

      $.ajax({
              url: url_event_add,
              type: "POST",
              data: {
                          title:title,
                          start:start1,
                          end:end1,
                             ...............
      
      
              },
      .........

      Et côté Symfony tu récupères les valeurs avec :

      $request->get('title'),

      A+


      -
      Edité par monkey3d 6 avril 2020 à 12:17:37

      • Partager sur Facebook
      • Partager sur Twitter
        6 avril 2020 à 13:17:38

        Bonjour,

        Merci pour ta réponse.

        1) Qu'entends-tu par variable valorisés ?

        Est-ce que c'est le fait de vérifier que mes variables contiennent une valeur ?

        2) je transmet un paramètre dans l'url car l'admin peut gérer le calendrier de plusieurs utilisateurs

        Pour plus de clarté je l'ai refais différement selon ton exemple, à présent title, start & end ne contienne plus undefined, mais elles sont vides

        			    drop: function(info) {
        						$.ajax({
        								{% if idSalarie is defined %}
        										url: '{{ path('cli_planning_calendar_ajout', {'id': idSalarie }) }}',
        								{% else %}
        										url: '{{ path('cli_planning_calendar_ajout', {'id': app.user.id }) }}',
        								{% endif %}
        								type: "POST",
        								data: {
        										title:info.title,
        										start:info.start,
        										end:info.end,
        								}
        							});
        			  });

        Peut-être ais-je louper quelque chose je penser que l'ont pouvais simplement récupérer la date où a été ajouté l'événement en faisant info.start, mais peut-être faut-il définir cet valeur d'une autre manière ?

        • Partager sur Facebook
        • Partager sur Twitter
          6 avril 2020 à 13:25:34

          1) oui

          2) tu peux transmettre l'id du user comme pour les autres data.

          3) pourquoi ajoutes tu info.xxx ????

          Dans ton code moi je vois :

          var start = info.start.format("YYYY-MM-DD HH:mm:ss");
          var end = info.end.format("YYYY-MM-DD HH:mm:ss");

          Donc il te suffit de mettre ces variables côté js.

          A+

          -
          Edité par monkey3d 6 avril 2020 à 13:25:43

          • Partager sur Facebook
          • Partager sur Twitter
            6 avril 2020 à 13:30:22

            Car je l'ai fais en raccourci pour une meilleur lisibilité j'étais passer sans les variables,  directement en passant par info.start

            Mais justement le problème c'est que le contenu de ces variables "start & end" est "undefined" si je fais

            						var start = info.start.format("YYYY-MM-DD HH:mm:ss");
            						var end = info.end.format("YYYY-MM-DD HH:mm:ss");
            						$.ajax({
            								{% if idSalarie is defined %}
            										url: '{{ path('cli_planning_calendar_ajout', {'id': idSalarie }) }}',
            								{% else %}
            										url: '{{ path('cli_planning_calendar_ajout', {'id': app.user.id }) }}',
            								{% endif %}
            								type: "POST",
            								data: {
            										id:info.id,
            										title:info.title,
            										start:start,
            										end:end,
            								}
            							});


            La date de début et de fin n'arrivent pas à être récupérer et s'affiche comme undefined tout comme tout les autres paramètres de data d'ailleurs

            -
            Edité par TuxZero 6 avril 2020 à 13:32:29

            • Partager sur Facebook
            • Partager sur Twitter
              6 avril 2020 à 14:17:06

              As tu vérifié que tes variables 

              var start = info.start.format("YYYY-MM-DD HH:mm:ss");
              var end = info.end.format("YYYY-MM-DD HH:mm:ss");

              étaient valorisées ?

              un petit console.log ...

              Et pour ton user :

              Tu fais une variable avec une ternaire (encore plus simple qu'un if) et tu passes dans le data.

              A+

              -
              Edité par monkey3d 6 avril 2020 à 14:18:45

              • Partager sur Facebook
              • Partager sur Twitter
                6 avril 2020 à 16:14:33

                Lorsque je vérifie dans l'inspecteur, dans les valeurs retourner par console.log je ne trouve pas mes variables start & end

                -
                Edité par TuxZero 6 avril 2020 à 16:47:30

                • Partager sur Facebook
                • Partager sur Twitter
                  6 avril 2020 à 16:52:18

                  Alors commence par là car si tes variables ne sont pas valorisées dans le js, c'est sûr que tu vas transmettre du vide.

                  Pourquoi préfixes tu toujours par info ???

                  A+

                  • Partager sur Facebook
                  • Partager sur Twitter
                    6 avril 2020 à 17:05:33

                    Si je ne préfixe pas par info comment accéder aux données relatif à l’événement déposer ?

                    • Partager sur Facebook
                    • Partager sur Twitter
                      6 avril 2020 à 17:16:25

                      Je ne sais pas ce que c'est qu'info. Moi je n'ai jamais info ... à la rigueur event ou events suivant le cas.

                      A+

                      • Partager sur Facebook
                      • Partager sur Twitter
                        6 avril 2020 à 17:27:59

                        Enfait le seul champs que je peut récupérer c'est le champs Date, mais du coups je peut avoir que la date de début et non de fin et en string et non datetime comme il me faut, je pourrais bien adapter mon entité pour la recevoir en string, mais c'est pas vraiment ce que je cherche à faire et cela pourrait compliquer toutes la suite.

                        -
                        Edité par TuxZero 6 avril 2020 à 18:18:33

                        • Partager sur Facebook
                        • Partager sur Twitter
                          6 avril 2020 à 18:25:54

                          Je ne sais plus où tu en es car c'est quoi le champs Date dans ton js ????

                          As tu essayé avec event comme proposé ?

                          Moi cela fonctionne et je stocke la date sous la forme d'un objet DateTime bien-sûr et pas un string. Le js envoit un  string mais ensuite je le transforme en objet DateTime.

                          A+

                          • Partager sur Facebook
                          • Partager sur Twitter
                            6 avril 2020 à 18:35:04

                            Oui j'ai essayer avec event comme proposé le résultat est identique

                            mon code actuel :

                            			    drop: function(event) {
                            							console.log(event);
                            	            var start = event.start.format("YYYY-MM-DD HH:mm:ss");
                            	            var end = event.end.format("YYYY-MM-DD HH:mm:ss");
                            
                            							var xhr = $.ajax({
                            									{% if idSalarie is defined %}
                            											url: '{{ path('cli_planning_calendar_ajout', {'id': idSalarie }) }}',
                            									{% else %}
                            											url: '{{ path('cli_planning_calendar_ajout', {'id': app.user.id }) }}',
                            									{% endif %}
                            									data: {
                            												id:event.id,
                            												title:event.innerText,
                            												start:start,
                            												end:end,
                            									},
                            									type: "POST",
                            									success: function(data) {
                            											console.log(data);
                            											window.location.reload(true);
                            											//alert(json);
                            									},
                            									error: function() {
                            											alert("erreur lors de l'appel de l'url dans POST event/drop : contactez l'administrateur du site");
                            									},
                            							});
                            			      // is the "remove after drop" checkbox checked?
                            			      if (checkbox.checked) {
                            			        // if so, remove the element from the "Draggable Events" list
                            			        event.draggedEl.parentNode.removeChild(event.draggedEl);
                            			      }
                            			    }
                            			  });
                            



                            -
                            Edité par TuxZero 6 avril 2020 à 18:36:10

                            • Partager sur Facebook
                            • Partager sur Twitter
                              6 avril 2020 à 18:38:32

                              En tout cas, je vois que dans event il y a des choses.

                              Faut sans doute explorer.

                              A+

                              • Partager sur Facebook
                              • Partager sur Twitter
                                6 avril 2020 à 18:41:35

                                Finalement en utilisant eventReceive à l'instar de drop j'arrive à voir start & end

                                Cependant je n'arrive pas à le formater de la sorte :format("YYYY-MM-DD HH:mm:ss")

                                Les seuls fonctions disponible étant :

                                Suis-je obligé de faire quelque chose comme cela :

                                		var year = event.event._instance.range.start.getFullYear();
                                		var day = event.event._instance.range.start.getDay();
                                		var month = event.event._instance.range.start.getMonth();
                                		var hours = event.event._instance.range.start.getHours();
                                		var minutes = event.event._instance.range.start.getMinutes();
                                	            var start = year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':00';

                                 Cela ne fonctionne pas et je pense que ce n'est de toutes façon pas la façon idéal, mais ayant fais quasiement toutes les fonctions je ne trouve pas celle qui me formatterais ma date en datetime

                                -
                                Edité par TuxZero 7 avril 2020 à 1:28:30

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  7 avril 2020 à 7:06:53

                                  Tu as plein de fonction javascript sur les dates :

                                  https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Date/parse

                                  Mais pourquoi la transformer côté JS ?

                                  Tu veux l'insérer en base si j'ai bien compris alors fais le côté serveur en php.

                                  Par exemple : https://www.php.net/manual/fr/datetime.createfromformat.php

                                  A+

                                  -
                                  Edité par monkey3d 7 avril 2020 à 7:08:29

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    7 avril 2020 à 19:36:38

                                    Bonjour,

                                    Effectivement je chercher bêtement a avancer tête baisser sans même voir plus loin que le bout de mon nez, en le faisant côté serveur en php sa fonctionne très bien, il m'a aussi fallu passer la fonction .toUTCString, à présent cela s'enregistre parfaitement, un grand merci pour ta précieuse aide.

                                    Bonne journée et bon confinement :)

                                    A+

                                    -
                                    Edité par TuxZero 7 avril 2020 à 19:37:30

                                    • Partager sur Facebook
                                    • Partager sur Twitter

                                    [SF 4.4] Draggable External Event Fullcalendar v4

                                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                    • Editeur
                                    • Markdown