Search code examples
javascriptphpjsonajaxdatepicker

Why doesn't it recognize any selections on the datepicker?


I'm trying to populate a select dropdown with the hours that don't have appointments booked, and right now I'm experiencing somethin really dumb with datepicker, because I want it to be populated based on the selected doctor in the selected day, but it seems to not even recognize that a day has been selected When I do select it.

This is my AJAX call

<script>
    $(document).ready(function(){
        $('#datepicker').datepicker({
            onSelect: function() {
                setTimeout(triggerAjaxCall, 0);
            }
        });

        $('#selMedico').change(function(){
            triggerAjaxCall();
        });

        function triggerAjaxCall() {
            var doctor = $('#selMedico').val();
            var date = $('#datepicker').val();

            console.log('Doctor:', doctor);
            console.log('Date:', date); 

            if (!doctor || !date) {
                console.log('Doctor or date not selected');
                return;
            }

            // AJAX call
            $.ajax({
                type: 'POST',
                url: 'fetchConsultas.php',
                data: { medico: doctor, dia: date },
                dataType: 'json',
                success: function(response) {
                    console.log('AJAX request successful');
                    console.log('Response:', response);  

                    $('#hora').empty();
                    $.each(response, function(index, value) {
                        $('#hora').append('<option value="' + value + '">' + value + '</option>');
                    });
                },
                error: function(jqXHR, textStatus, errorThrown) {
                    console.log('AJAX request failed:', textStatus, errorThrown);  
                }
            });
        }
    });
</script>

and this is my fetchConsultas.php file

<?php
if (isset($_POST['medico']) && isset($_POST['dia'])) {

    $medicoSelecionado = $_POST['medico'];
    $dataSelecionada = $_POST['dia'];

    include 'connection.php';

    $stmt = $pdo->prepare('SELECT id_hora 
                            FROM tabconsultas 
                            WHERE id_medico = ? 
                            AND id_dia = ? ;');
    
    $stmt->execute([$medicoSelecionado, $dataSelecionada]);

    $horarios = $stmt->fetchAll(PDO::FETCH_COLUMN, 0);

    // Create an array of all the hours from 08:00:00 to 18:00:00 (excluding 13:00:00)
    $allHours = [];
    for ($i = 8; $i <= 18; $i++) {
        if ($i != 13) {
            $hour = str_pad($i, 2, '0', STR_PAD_LEFT) . ':00:00';
            $allHours[] = $hour;
        }
    }

    // Get the hours that are not in the result of the query
    $availableHours = array_diff($allHours, $horarios);

    echo json_encode($availableHours);

    $pdo = null;
    $stmt = null;
} else {
    echo "No doctor or date selected.";
}
die();

I'm pretty sure that there's something wrong with the datepicker plugin itself, but I'm not very experienced, so I'm hoping someone can help me find out a way to go over this.

Note: It actually populates the dropdown correctly If I :

  • select a doctor and then select a date, then select another random doctor and finally go back to the doctor selected at first.

Just like what's happening here:

Console logs

As you can see, it goes from doctor 2 with no date, to doctor 6 with a date, because it only triggers when I select a doctor, and it should be triggering when I select a doctor AND a date!

As asked in the post, I'm addin the HTML code for doctor selection and date.

 $consulta = "SELECT DISTINCT tabutilizador.id_utilizador, tabutilizador.nome  
                    FROM tabutilizador
                    LEFT JOIN tabconsultas ON tabutilizador.id_utilizador = tabconsultas.id_medico 
                    WHERE tabutilizador.tipo = 'medico'";

        $resultado = $conexao->query($consulta);
        //Lista de médicos
        echo '<form id="formulario" action="formhandler.inc.php" method="POST">';
        echo '<label for="medico">Médico</label><br><br>';
        echo '<select id="selMedico" name="medico" onchange="fetchServicosPorMedico(this.value)" required>';
        echo '<option value="" disabled select selected>Escolha um Médico</option>';
        while ($linha = $resultado->fetch_assoc()) {
            echo '<option value="' . $linha['id_utilizador'] . '">' . $linha['nome'] . '</option>';
        }
        echo '</select><br><br>';

and as for the date:

echo '<label for="dia">Data da Consulta</label><br><br>';
        echo '<input type="text" id="datepicker" name="dia" placeholder="Selecione uma data" required><br><br>';

I'm also adding the overall scheme of the database, as it was also asked:

database schema

I've been thinking, and as I've destroyed and generated a new datepicker before, in order to populate it correctly enabling only the days the selected doctor works on, I guess something around here might be causing this to happen?

    <script>
    $(document).ready(function() {
        $('#selMedico').change(function() {
            var medicoSelecionado = $(this).val();
            $.ajax({
                url: 'fetchDiasPorMedico.php',
                type: 'post',
                data: {
                    medico: medicoSelecionado
                },
                success: function(response) {
                    $('#resultado').html(response);
                    var diasDisp = response;
                    $(function() {
                        $("#datepicker").datepicker("destroy").datepicker({
                            dateFormat: 'yy-mm-dd',
                            dayNames: ['Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado'],
                            dayNamesMin: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'],
                            dayNamesShort: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'],
                            monthNames: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
                            monthNamesShort: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'],
                            nextText: 'Próximo',
                            prevText: 'Anterior',
                            beforeShowDay: function(date) {
                                var day = date.getDay();
                                // Avalia a lógica em qualquer para determinar se o dia deve ser desabilitado
                                var disableDay = new Function('day', 'return ' + diasDisp);
                                return [disableDay(day), ''];
                            },
                            onSelect: function(dateText, inst) {
                                var selectedDate = $(this).datepicker('getDate');
                                var dayOfWeek = selectedDate.getDay();
                            },
                            minDate: 0
                        });
                    });
                }
            });
        });
    });

Solution

  • I created this codesnippet only to make sure that doctor and date both can be selected perfectly.

    Check the codesnippet here (Hope this can help you):

    $( function() {
        $( "#datepicker" ).datepicker({
          onSelect: function() {
                    setTimeout(triggerAjaxCall, 0);
                }
        });
         $('#selMedico').change(function() {
                var medicoSelecionado = $(this).val();
                        var diasDisp = [true, true, false, true, false, true]; //The response returned from server will appear here
    
    // remove $(function() { }) 
    // do not initiate datepicker here within $(function()) as this will work only on load not work dynamically. 
    //So simply implement within the server response block
    
    $("#datepicker").datepicker("destroy").datepicker({
                                dateFormat: 'yy-mm-dd',
                                dayNames: ['Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado'],
                                dayNamesMin: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'],
                                dayNamesShort: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'],
                                monthNames: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
                                monthNamesShort: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'],
                                nextText: 'Próximo',
                                prevText: 'Anterior',
                                beforeShowDay: function(date) {
                                    var day = date.getDay();
                                    // Avalia a lógica em qualquer para determinar se o dia deve ser desabilitado
                                    var disableDay = new Function('day', 'return ' + diasDisp[day]);
                                    return [disableDay(day), ''];
                                },
                                onSelect: function(dateText, inst) {
                                    var selectedDate = $(this).datepicker('getDate');
                                    var dayOfWeek = selectedDate.getDay();
                                    setTimeout(triggerAjaxCall, 0); // Call triggerAjaxCall here, You forgot to call here
                                },
                                minDate: 0
                                
                            });
                        });
                    
                
        
      } );
    function triggerAjaxCall() {
                var doctor = $('#selMedico').val();
                var date = $('#datepicker').val();
                             
                if (!doctor || !date) {
                    alert('Doctor or date not selected');
                    return;
                }
                else
                {
                  alert("Doctor: " + doctor+"   Date: "+date);
                }
      /*
      Here comes the AJAX POST request code 
      */
    }
    <html>
      <head>
          <link rel="stylesheet" href="https://code.jquery.com/ui/1.13.3/themes/base/jquery-ui.css">
      <link rel="stylesheet" href="/resources/demos/style.css">
      <script src="https://code.jquery.com/jquery-3.7.1.js"></script>
      <script src="https://code.jquery.com/ui/1.13.3/jquery-ui.js"></script>
      </head>
      <body>
        <div id="doctorselection">
          <form id="docselform">
            <label>Select Doctor: </label>
            <select id="selMedico"> 
              <option value="" selected> Select a Doctor</option>
              <option value="DR. ABC"> Dr. ABC</option>
              <option value="DR. XYZ"> Dr. XYZ</option>
              <option value="DR. PQR"> Dr. PQR</option>
            </select>
           <br />
           <label>Select Date: </label>     
            <input type="text" id="datepicker" />    
          </form>
        </div>
      </body>
    </html>

    EDIT In your edited question you mentioned

    "I've been thinking, and as I've destroyed and generated a new datepicker before..."

    You are right . on $(document).ready(function() {}) the datepicker was inititalized which was triggering the function triggerAjaxCall on date selection , but when its destroying and reinitiating datepicker then you forgot to add triggerAjaxCall.

    As you can see, it goes from doctor 2 with no date, to doctor 6 with a date, because it only triggers when I select a doctor, and it should be triggering when I select a doctor AND a date!

    This is because you called triggerAjaxCall within $('#selMedico').change(function(){ ...}), call it in Datepicker Option onSelect

    In your code you have implemented datePicker destroy and reintializaiton within $(function(){....}) which is being called within $('#selMedico').change(function() { ... }) . $(document).ready(function() {}) and $(function(){....}) are same both of them triggered when DOM is ready. But within onChange function you need not to call onReady , write the code of datePicker destroy outside $(function(){....})

    Now recheck the code snippet, I tried to create the scenario with static data (no ajax, no php). Check, compare with your code and replace as necessary