Skip to main content

Overview

The MultiDateFilter class provides a multi-date picker using Flatpickr, allowing users to select multiple individual dates. It applies an orWhereDate query for each selected date.

Creating a MultiDateFilter

make
static method
required
Creates a new MultiDateFilter instance.
field
string
required
The database column name to filter on
MultiDateFilter::make('event_date')

Available Methods

label

label
method
Sets the display label for the filter.
label
string
required
The label text to display
MultiDateFilter::make('event_date')
    ->label('Event Dates')

format

format
method
Sets the date format for display and parsing.
format
string
required
Date format string (PHP date format)
MultiDateFilter::make('event_date')
    ->format('Y-m-d')
Default: 'Y-m-d'

minDate

minDate
method
Sets the minimum selectable date.
date
string
required
Minimum date in ‘Y-m-d’ format
MultiDateFilter::make('event_date')
    ->minDate('2024-01-01')

maxDate

maxDate
method
Sets the maximum selectable date.
date
string
required
Maximum date in ‘Y-m-d’ format
MultiDateFilter::make('event_date')
    ->maxDate('2025-12-31')

key

key
method
Overrides the internal key used for the filter.
key
string
required
Custom key identifier
MultiDateFilter::make('event.date')
    ->key('event_date_multi')

default

default
method
Sets default date values for the filter.
value
mixed
required
The default value (array of date strings)
MultiDateFilter::make('event_date')
    ->default(['2024-03-15', '2024-03-20'])

initialValue

initialValue
method
Sets initial date values that are pre-applied when the table first loads.
value
mixed
required
The initial value (array of date strings)
MultiDateFilter::make('scheduled_date')
    ->initialValue([
        now()->format('Y-m-d'),
        now()->addDay()->format('Y-m-d'),
    ])

filter

filter
method
Provides a custom query callback to override the default filter behavior.
callback
Closure
required
A closure that receives Builder $query and mixed $value (array of date strings) and returns the modified Builder
MultiDateFilter::make('event_date')
    ->label('Event Dates')
    ->filter(function (Builder $query, mixed $value) {
        if (is_array($value) && count($value) > 0) {
            return $query->whereIn('event_date', $value);
        }
        return $query;
    })

groupClass / labelClass / inputClass

groupClass
method
Sets CSS classes for the filter wrapper, label, or input element.
MultiDateFilter::make('event_date')
    ->groupClass('col-md-6')
    ->labelClass('font-semibold')
    ->inputClass('form-control-lg')

Value Structure

The filter value is an array of date strings:
['2024-03-15', '2024-03-20', '2024-03-25']
An empty array means no filter is applied:
[]  // No filter applied

Value Normalization

Date values are automatically filtered to remove:
  • Non-string values
  • Empty strings
  • Dates outside minDate/maxDate bounds
MultiDateFilter::make('event_date')
    ->minDate('2024-01-01')
    ->maxDate('2024-12-31')
If the user selects ['2023-12-15', '2024-06-15', '2025-01-15'], the normalized value will be ['2024-06-15'].

Default Behavior

By default, MultiDateFilter applies orWhereDate queries for each selected date:
$query->where(function (Builder $q) use ($dates) {
    foreach ($dates as $date) {
        $q->orWhereDate($fieldName, $date);
    }
});
This matches records where the field equals any of the selected dates.

Complete Examples

Basic Usage

use Livewire\Tables\Filters\MultiDateFilter;

public function filters(): array
{
    return [
        MultiDateFilter::make('event_date')
            ->label('Event Dates')
            ->format('Y-m-d')
            ->minDate('2024-01-01')
            ->maxDate('2025-12-31'),

        MultiDateFilter::make('scheduled_date')
            ->label('Scheduled Dates'),

        MultiDateFilter::make('deadline')
            ->label('Deadlines')
            ->format('m/d/Y'),
    ];
}

Pre-selected Dates

use Livewire\Tables\Filters\MultiDateFilter;

public function filters(): array
{
    return [
        // Default to today and tomorrow
        MultiDateFilter::make('event_date')
            ->label('Event Dates')
            ->initialValue([
                now()->format('Y-m-d'),
                now()->addDay()->format('Y-m-d'),
            ]),

        // Default to weekdays in current week
        MultiDateFilter::make('workday')
            ->label('Workdays This Week')
            ->initialValue([
                now()->startOfWeek()->format('Y-m-d'),
                now()->startOfWeek()->addDays(1)->format('Y-m-d'),
                now()->startOfWeek()->addDays(2)->format('Y-m-d'),
                now()->startOfWeek()->addDays(3)->format('Y-m-d'),
                now()->startOfWeek()->addDays(4)->format('Y-m-d'),
            ]),
    ];
}

Custom Filter Logic

use Livewire\Tables\Filters\MultiDateFilter;
use Illuminate\Database\Eloquent\Builder;

public function filters(): array
{
    return [
        MultiDateFilter::make('available_date')
            ->label('Available Dates')
            ->filter(function (Builder $query, mixed $value) {
                if (is_array($value) && count($value) > 0) {
                    return $query->where(function (Builder $q) use ($value) {
                        foreach ($value as $date) {
                            $q->orWhere(function (Builder $subQ) use ($date) {
                                $subQ->whereDate('start_date', '<=', $date)
                                     ->whereDate('end_date', '>=', $date);
                            });
                        }
                    });
                }
                return $query;
            }),

        MultiDateFilter::make('holiday')
            ->label('Exclude Holidays')
            ->filter(function (Builder $query, mixed $value) {
                if (is_array($value) && count($value) > 0) {
                    return $query->whereNotIn('date', $value);
                }
                return $query;
            }),
    ];
}

Usage in Table Component

use App\Models\Event;
use Illuminate\Database\Eloquent\Builder;
use Livewire\Tables\Filters\MultiDateFilter;
use Livewire\Tables\Filters\SelectFilter;
use Livewire\Tables\Livewire\DataTableComponent;

class EventsTable extends DataTableComponent
{
    public function query(): Builder
    {
        return Event::query();
    }

    public function filters(): array
    {
        return [
            MultiDateFilter::make('event_date')
                ->label('Event Dates')
                ->format('Y-m-d')
                ->minDate(now()->format('Y-m-d')),

            MultiDateFilter::make('registration_deadline')
                ->label('Registration Deadlines'),

            SelectFilter::make('category_id')
                ->label('Category')
                ->setOptions(Category::pluck('name', 'id')->toArray()),
        ];
    }
}

Real-world Example: Appointment Scheduling

use Livewire\Tables\Filters\MultiDateFilter;
use Illuminate\Database\Eloquent\Builder;

public function filters(): array
{
    return [
        MultiDateFilter::make('appointment_date')
            ->label('Appointment Dates')
            ->format('Y-m-d')
            ->minDate(now()->format('Y-m-d'))
            ->maxDate(now()->addMonths(3)->format('Y-m-d'))
            ->filter(function (Builder $query, mixed $value) {
                if (is_array($value) && count($value) > 0) {
                    return $query->where(function (Builder $q) use ($value) {
                        foreach ($value as $date) {
                            $q->orWhereDate('scheduled_at', $date);
                        }
                    });
                }
                return $query;
            }),
    ];
}

Date Format Examples

// US format
MultiDateFilter::make('date')
    ->format('m/d/Y')

// European format
MultiDateFilter::make('date')
    ->format('d/m/Y')

// ISO format (default)
MultiDateFilter::make('date')
    ->format('Y-m-d')

// With month name
MultiDateFilter::make('date')
    ->format('M d, Y')

UI Rendering

The filter renders a single input field that opens a Flatpickr calendar in multiple selection mode when clicked. Users can click multiple dates, and all selected dates are displayed in the input field separated by commas.

Build docs developers (and LLMs) love