skip to Main Content

Following this question and this other question, I managed to create the flatpickr element and to send data to the backend. The problem is that, although in the Rule that validates the datetime the passes method returns false, the validation error is not shown in the form.

For sake of easy-reading, this is the blade portion for the datepicker:

<div class="mb-3" wire:ignore>
    <label for="pickeddatetime" class="form-label">Date and time</label>
    <input id="pickeddatetime" class="form-control @error('pickeddatetime') is-invalid @enderror"
           type="datetime-local" name="pickeddatetime" placeholder="Pick a date and time"
           value="{{ old('pickeddatetime') }}" wire:model.debounce.500ms="pickeddatetime">
    @error('pickeddatetime')
    <p class="invalid-feedback">{{ $errors->first('pickeddatetime') }}</p>
    @enderror
</div>

I believe it is due to the wire:ignore directive (used to make flatpickr work with Livewire) preventing any change in the DOM but, again, I’m still learning and thus be completely wrong.

2

Answers


  1. To work around this, you can use a JavaScript event that will manually emit an event to Livewire when your datepicker’s value changes.

    <div class="mb-3" wire:ignore>
        <label for="pickeddatetime" class="form-label">Date and time</label>
        <input id="pickeddatetime" class="form-control @error('pickeddatetime') is-invalid @enderror"
               type="text" placeholder="Pick a date and time"
               value="{{ old('pickeddatetime') }}">
        @error('pickeddatetime')
        <p class="invalid-feedback">{{ $errors->first('pickeddatetime') }}</p>
        @enderror
    </div>
    
    <script>
        flatpickr("#pickeddatetime", {
            enableTime: true,
            dateFormat: "Y-m-d H:i", // or your preferred date format
            onChange: function(selectedDates, dateStr, instance) {
                @this.set('pickeddatetime', dateStr);
            }
        });
    </script>
    
    Login or Signup to reply.
  2. You’re right, the wire:ignore on the parent div makes Livewire ignore any updates to that part of the DOM. It will never change anything inside of it.

    So, to make the paragraph show, simply move the wire:ignore down on the input itself.

    <div class="mb-3">
        <label for="pickeddatetime" class="form-label">Date and time</label>
        <input id="pickeddatetime" wire:ignore.self class="form-control @error('pickeddatetime') is-invalid @enderror"
               type="datetime-local" name="pickeddatetime" placeholder="Pick a date and time"
               value="{{ old('pickeddatetime') }}" wire:model.debounce.500ms="pickeddatetime">
        @error('pickeddatetime')
        <p class="invalid-feedback">{{ $errors->first('pickeddatetime') }}</p>
        @enderror
    </div>
    

    You will still need wire:ignore or wire:ignore.self on the input, as the Flatpickr library will modify and maintain state of the actual input.

    This only solves half of your issue though, as you will still not get the class is-invalid applied when the validation for that property fails. To achieve this, either put the class on a wrapper, and then apply CSS in such a way that it’ll be put on the input, or else you would need some sort of listener or change-event on the Flatpickr instance, and then check if the validation failed before applying or removing the class on the input, meaning that you apply it with JavaScript.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search