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

naykel's avatar
Level 7

Flatpickr not updating in realtime

I'm currently working on a datepicker component where I'm using Alpine.js and Livewire together to handle date inputs.

Here is my Pikaday implementation which works perfectly keeping both the input and date property in sync.

<input x-data wire:model.blur="selectedDate" x-ref="pikaDatepicker"
    x-init="new Pikaday({ field: $refs.pikaDatepicker, format: 'DD-MM-YYYY' })"
    x-on:change="$dispatch('input', $el.value)" type="text" />

And, here is my flatpickr implementation which is not working as expected. The date property is not updating in real-time. It only updates when I click outside the input field.

<input x-data wire:model.blur="selectedDate" x-ref="datePickerInput"
    x-init="flatpickr($refs.datePickerInput, {
        dateFormat: 'd-m-Y',
        onChange: (selectedDates, dateStr) => $dispatch('input', dateStr)
    })" type="text">

Any help would be appreciated.

0 likes
3 replies
RemiM's avatar

Flatpickr doesn’t automatically trigger an input event when a date is selected, unlike Pikaday. Instead, it uses its own onChange event, whereas Livewire relies on standard input events to detect changes.

Since wire:model.blur only updates Livewire when the field loses focus, you need to manually dispatch an input event to ensure real-time updates.

<input x-data wire:model="selectedDate" x-ref="datePickerInput"
    x-init="flatpickr($refs.datePickerInput, {
        dateFormat: 'd-m-Y',
        onValueUpdate: (selectedDates, dateStr) => {
            $refs.datePickerInput.value = dateStr;  // Update input value
            $dispatch('input', dateStr);  // Ensure Livewire detects the change
        }
    })" type="text">

Note: Instead of using onChange, which triggers only when a date is fully selected, onValueUpdate ensures Livewire updates as soon as the value changes. That said, the choice depends on your specific needs.

naykel's avatar
Level 7

You’re right that the onChange event doesn’t automatically trigger an input event when a date is selected (it took me ages to figure that out this morning.)

I tried your solution, but unfortunately, it didn’t work for me. I believe the issue is that Flatpickr cannot access Alpine's $dispatch method, so Livewire doesn’t detect the change. That’s why I had to add .blur to the wire:model directive, which makes it "sort of" work.

For anyone who wants a "sort of working" datepicker, here’s the full component:)

<?php

namespace App\Livewire\Gotime\Forms;

use App\Models\User;
use Livewire\Component;

class Datepicker extends Component
{
    public User $user;

    public $selectedDate;

    public function mount()
    {
        $this->user = User::first();
        $this->selectedDate = $this->user->created_at->format('d-m-Y');
    }

    public function render()
    {
        return <<<'BLADE'
        <div>
            <div><strong>Date: </strong>{{ $selectedDate }}</div>

            <input x-data wire:model.blur="selectedDate" x-ref="datePickerInput"
                x-init="flatpickr($refs.datePickerInput, {
                    dateFormat: 'd-m-Y',
                    onChange: (selectedDates, dateStr) => {
                        $dispatch('input', dateStr);
                    } })" type="text">
            @once
                @push('styles')
                    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
                @endpush
                @push('scripts')
                    <script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
                @endpush
            @endonce
        </div>
        BLADE;
    }
}
RemiM's avatar

@naykel I see what you mean. I wonder if manually triggering an actual input event on the field would work, since Livewire listens for those events.

Something like that:

<input x-data x-ref="datePickerInput" wire:model="selectedDate"
    x-init="flatpickr($refs.datePickerInput, {
        dateFormat: 'd-m-Y',
        onChange: (selectedDates, dateStr) => {
            $refs.datePickerInput.value = dateStr; // Update input field
            $refs.datePickerInput.dispatchEvent(new Event('input', { bubbles: true })); // Ensure Livewire detects it
        }
    })" type="text">

Note: the { bubbles: true } option allows the event to propagate up the DOM, making it easier for Livewire to detect.

That said, you've already found a workaround, but having something that only "sort of" works can be frustrating. If this version improves reliability, it would definitely be worth trying.

Please or to participate in this conversation.