Search code examples
javascripthtmlformsdateinput

How can I restrict some exact days of the week with input type=date?


The main problem is that I can select from Monday to Sunday and I want to restrict Tuesdays, Thursdays, Saturdays and Sundays and only select Mondays, Wednesdays and Fridays This is the code I tried but I don't actually know why it doesn't work:

Thanks!!!!!

<form action="insertar_reserva_tarde.php" method="POST">
    <label for="fecReserva">Día:</label>
    <input type="date" name="fecReserva" id="fecReserva" min="2023-06-15" max="2023-07-15"required>
    <br>
    <label for="horIniReserva">Hora de inicio:</label>
    <select name="horIniReserva" id="horIniReserva">
        <option value="17">17:00</option>
        <option value="18">18:00</option>
        <option value="19">19:00</option>
        <option value="20">20:00</option>
    </select>
    <br>
    <label for="horFinReserva">Hora de fin:</label>
    <select name="horFinReserva" id="horFinReserva">
        <option value="18">18:00</option>
        <option value="19">19:00</option>
        <option value="20">20:00</option>
        <option value="21">21:00</option>
    </select>
    <br>
    <input type="hidden" name="pista" value="1">
    <input type="hidden" name="idHorario" value="1">
    <input type="submit" value="Reservar">
</form>
<?php
        if(isset($_POST['fecReserva'])){
            $date = strtotime($_POST['fecReserva']);
            $dayOfWeek = date('N', $date); // obtiene el número del día de la semana (1 = lunes, 2 = martes, etc.)
            if($dayOfWeek == 1 || $dayOfWeek == 3 || $dayOfWeek == 5){
                echo "<p>La fecha seleccionada es el ".date('d/m/Y', $date)."</p>";
            } else {
                echo "<p>Sólo se permiten reservas en Lunes, Miércoles y Viernes.</p>";
            }
        }
    ?>
    <script>// Everything except weekend days
        const validate = dateString => {
        const day = (new Date(dateString)).getDay();
        if (day==2 || day==4 || day==6 || day==0 ) {
            return false;
        }
        return true;
        }

        // Sets the value to '' in case of an invalid date
        document.querySelector('input').onchange = evt => {
        if (!validate(evt.target.value)) {
            evt.target.value = '';
        }
        }
    </script>

The intention is to only select Mondays, Wednesdays and Fridays


Solution

  • Your issue seems to be that you're attaching the listener to the input's change event, then returning false to that event.

    If you only want to select odd numbered days (based on ECMAScript day numbering) then the function just needs to return the result of !!(dayNum % 2).

    The value of an input type date is a timestamp in the format YYYY-MM-DD, which will be parsed as UTC so if using new Date(value) you need to get the UTC day.

    The following illustrates the logic through display of a message, form submission is deliberately cancelled so both success and failure are demonstrated without submitting.

    There are many other ways of achieving the same result, e.g. you could use valueAsDate rather than calling the Date constructor. You could also use an array of allowed or not allowed days and test against that, and so on.

    window.onload = () => {
    
      // Related elements
      let form = document.getElementById('calendar');
      let msg = document.getElementById('msg');
      
      // The listener
      let checkDate = evt => {
      
        // Cancel submit if called from submit
        if (evt.type == 'submit') evt.preventDefault();
        
        // Value parsed as UTC so get UTC day
        let day = new Date(form.theDate.value).getUTCDay();
        // Check if day is valid
        let isValid = !!(day % 2);
        
        // Do stuff based on whether isValid is true or false
        // Show message based on selected day
        let days = ['Sunday','Monday','Tuesday','Wednesay','Thursday','Friday','Saturday']
        msg.textContent = `Selected day is ${days[day]}, ` +
          `${isValid? 'pass.' : 'fail. Must be a Monday, Wednesday or Friday'}`;
          
        return isValid;
      }
      
      // Attach listeners - deal with form being submitted without setting a date
      form.addEventListener('change', checkDate);
      form.addEventListener('submit', checkDate);
    }
    #msg {
      color: #999999;
      font-family: sans-serif;
    }
    <form id="calendar" onsubmit="return false">
      <label for="theDate">Date:</label>
      <input type="date" id="theDate" name="theDate">
      <span id="msg"></span><br>
      <button>Submit</button>
    </form>

    It's more user friendly to not clear user input if it's invalid. Just advise users that something is wrong and let them fix it themselves. In this case, they may have selected an incorrect day but in fixing it, they can see which day they previously selected and can pick one either side.

    If the value is cleared, they likely have to remember which day they originally selected or start their logic for day selection over again.