Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

wise311's avatar

Livewire + Flatpickr auto update disabled date based on selected value.

Hi!

I'm trying to make a Livewire working with Flatpickr. Basically, I want to create a booking form for specific facility. If selected facility has some bookings with specific dates, then I want to disable those dates on flatpickr. Every Facilities Select Change should update flatpickr disabled dates by this facility bookings.

Livewire Controller BookingCreate.php

use App\Models\Booking;
use App\Models\BookingsStatus;
use App\Models\Facility;
use App\Models\User;
use Livewire\Component;

class BookingCreate extends Component
{
    public $facilities;
    public $facility_id;
    public $facilityPrice;
    public $bookings;

    protected $rules = [
        'facility_id' => 'required'
    ];

    public function mount() {
        $this->facilities = Facility::all();
        $this->facilityPrice = $firstFacility = Facility::first(); //loads first facility by default
        $this->bookings = Booking::where('facility_id', $firstFacility->id)->get();
    }

    public function render()
    {
        return view('livewire.booking-create', [
            'users' => User::whereHas("roles", function($q){ $q->where("name", "user"); })->get(),
            'statuses' => BookingsStatus::get(),
        ]);
    }

    public function updatedFacilityId($value) {
        $this->facilityPrice = Facility::findOrFail($value);
        $this->bookings = Booking::where('facility_id', $value)->get();
    }
}

Livewire view booking-create.blade.php

<div>
<form action="{{ route('bookings.store') }}" method="POST" class="p-10 bg-white rounded shadow-xl">
   @csrf
   <p class="text-lg text-gray-800 font-medium pb-4">New Booking</p>
   <div class="mb-4">
      <label class="block text-sm text-gray-600 mb-2" for="name">Facility</label>
      <select class="w-full px-2 py-1 text-gray-700 bg-gray-200 rounded" id="facility_id" name="facility_id" type="text" aria-label="name" wire:model="facility_id">
         <option disabled>Select Facility</option>
         @foreach($facilities as $facility)
         <option value="{{ $facility->id }}" {{ $loop->index == 0 ? 'selected' : '' }}>
         {{ $facility->name }}</option>
         @endforeach
      </select>
   </div>
   <div class="mb-4">
      <label class="block text-sm text-gray-600 mb-2">Facility Cost Per Day</label>
      <input type="text" name="facility_price" class="w-full px-2 py-1 text-gray-700 bg-gray-200 rounded" id="facility_price" value="{{ $facilityPrice->formattedPrice }}" readonly />
      <div class="mb-4">
         <label class="block text-sm text-gray-600 mb-2" for="name">User</label>
         <select class="w-full px-2 py-1 text-gray-700 bg-gray-200 rounded" id="user_id" name="user_id" type="text" aria-label="name">
            <option disabled selected>Select User</option>
            @foreach($users as $user)
            <option value="{{ $user->id }}">{{ $user->name }} ({{ $user->email }})</option>
            @endforeach
         </select>
      </div>
      <div class="mb-4">
         <label class="block text-sm text-gray-600 mb-2" for="name">Status</label>
         <select class="w-full px-2 py-1 text-gray-700 bg-gray-200 rounded" id="status_id" name="status_id" type="text" aria-label="name">
            <option disabled selected>Select Status</option>
            @foreach($statuses as $status)
            <option value="{{ $status->id }}">{{ $status->name }}</option>
            @endforeach
         </select>
      </div>
      <div wire:ignore class="mb-4">
         <label class="block text-sm text-gray-600 mb-2" for="date">Booking Arrival / Departure</label>
         <input type="text" name="date" class="flatpickr js-flatpickr-datetime w-full px-2 py-1 text-gray-700 bg-gray-200 rounded" id="date" />
      </div>
      <div class="mb-4">
         <label class="block text-sm text-gray-600 mb-2" for="price">Total Cost</label>
         <input type="text" name="price" class="w-full px-2 py-1 text-gray-700 bg-gray-200 rounded" id="price" readonly />
      </div>
      <div class="mt-6">
         <button class="px-4 py-1 text-white font-light tracking-wider bg-gray-900 rounded" type="submit">Add</button>
      </div>
</form>
<div wire:ignore>
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<script src="{{ asset('js/currency/currency.min.js') }}"></script>
</div>
<?php
   echo "<script>
       flatpickr('#date', {
           mode: 'range',
           minDate: 'today',
           dateFormat: 'Y-m-d',
           disable: [";
           foreach ($bookings as $book) {
               $booking = $book['date'];
               if($booking) {
                   if(str_contains($booking, 'to')) {
                       $booking = explode(" to ", $booking);
                       $from = $booking[0];
                       $to = $booking[1];
                       echo "
                       {
                       from: '".$from."',
                       to: '".$to."'
                       },
                       ";
                   } else {
                       echo "'$booking',";
                   }
               }
                   }
           echo "],
           onChange: function(selectedDates, dateStr, instance) {
               let daysInRange = document.getElementsByClassName('inRange');
               let daysLengthTotal = daysInRange.length + 1;
               let facilityPrice = document.getElementById('facility_price').value;
               let bookingTotal = document.getElementById('price');
               let calculation = facilityPrice * daysLengthTotal
               bookingTotal.value = currency(calculation, { fromCents: true }).format();
           }
       });
   </script>"; ?>
</div>

Flatpickr script in php tag is refreshed while changing selected facility. It updates disabled dates correctly, but flatpickr shows only a first facility disabled dates (from 1st page load). Any idea how can I get it working?

Sorry for my dirty code, I'm still learning. Thanks for your help.

0 likes
0 replies

Please or to participate in this conversation.