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.
Please or to participate in this conversation.