Skip to content

Instantly share code, notes, and snippets.

@janglapuk
Last active December 5, 2023 16:29
Show Gist options
  • Save janglapuk/4eeb3e85c0d90b516f092298bf8cc733 to your computer and use it in GitHub Desktop.
Save janglapuk/4eeb3e85c0d90b516f092298bf8cc733 to your computer and use it in GitHub Desktop.
DateRangePicker component in Laravel Livewire 3

DateRangePicker component in Laravel Livewire 3

image

Requirements

  1. Laravel + Livewire 3
  2. Bootstrap
  3. jQuery
  4. moment.js
  5. Date Range Picker

Commands

  1. php artisan make:livewire Date
  2. php artisan make:livewire DateComponent

Code Snippets

resources/views/layout.blade.php

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Livewire</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"
            integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">

        <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css" />
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fontawesome5-fullcss@1.1.0/css/all.min.css">

        @livewireStyles
    </head>

    <body>
        <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
            <div class="container-fluid">
                <a class="navbar-brand" href="/" wire:navigate>Livewire DateRangePicker</a>
            </div>
        </nav>
        <div class="container">
            {{ $slot }}
        </div>

        <script type="text/javascript" src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
        <script type="text/javascript" src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
        <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js"></script>

        @livewireScripts
    </body>
</html>

resources/views/livewire/date.blade.php

<div>
    <div class="row my-5">
        <div class="col-md-6">
            <div class="form-group mb-3">
                <label class="form-label" for="year">Year</label>
                <select wire:model="year" id="year" class="form-select" wire:change="changeYear">
                    <option value="2023">2023</option>
                    <option value="2024">2024</option>
                    <option value="2025">2025</option>
                    <option value="2026">2026</option>
                </select>
            </div>

            <div class="form-group mb-3">
                <label for="drp" class="form-label">DateRangePicker</label>
                <livewire:date-component key="{{ 'drp-' . uniqid() }}" :start="$start" :end="$end" />
            </div>

            <div>
                Debug:
                <ul>
                    <li x-text="$wire.year"></li>
                    <li x-text="$wire.start"></li>
                    <li x-text="$wire.end"></li>
                </ul>
            </div>
        </div>
    </div>
</div>

Note: key="{{ 'drp-' . uniqid() }}" is the trick to make child component "reactive". Source from here.

resources/views/livewire/date-component.blade.php

<div>  
    <div
        id="drp" 
        class="form-control" 
        style="background: #fff; cursor: pointer; padding: 5px 10px; border: 1px solid #ccc; width: 100%"
        x-data="{start: $wire.start, end: $wire.end}"
        x-init="
            let startDate = moment(start);
            let endDate = moment(end);
            let drp = $('#drp').daterangepicker({
                startDate: startDate,
                endDate: endDate,
                minDate: startDate.clone().startOf('year'),
                maxDate: startDate.clone().endOf('year'),
            }, function(s, e) {
                $('span', this.element).html(s.format('DD/MM/YYYY') + ' &rarr; ' + e.format('DD/MM/YYYY'));
                $wire.dispatch('update', [s.format('YYYY-MM-DD'), e.format('YYYY-MM-DD')]);
            });

            $('span', drp).html(startDate.format('DD/MM/YYYY') + ' &rarr; ' + endDate.format('DD/MM/YYYY'));
        "
    >
        <i class="fa fa-calendar"></i>&nbsp;
        <span></span> <i class="fa fa-caret-down"></i>
    </div> 
</div>

app/Livewire/Date.php

<?php

namespace App\Livewire;

use Livewire\Component;
use \Carbon\Carbon;

class Date extends Component
{
    public string $year = '';
    public string $start = '';
    public string $end = '';

    protected $listeners = [
        'update',
    ];

    public function update($start, $end) 
    {
        $this->year = carbon::parse($start)->format('Y');
        $this->start = $start;
        $this->end = $end;
    }

    public function changeYear()
    {
        $this->start = Carbon::parse($this->start)->year($this->year)->format('Y-m-d');
        $this->end = Carbon::parse($this->end)->year($this->year)->format('Y-m-d');
    }

    public function mount()
    {
        // First initialize
        $this->year = Carbon::now()->format('Y');
        $this->start = Carbon::now()->year($this->year)->firstOfMonth()->format('Y-m-d');
        $this->end = Carbon::now()->year($this->year)->lastOfMonth()->format('Y-m-d');
    }

    public function render()
    {
        return view('livewire.date')->layout('layout');
    }
}

app/Livewire/DateComponent.php

<?php

namespace App\Livewire;

use Livewire\Component;

class DateComponent extends Component
{
    public string $start = '';
    public string $end = '';

    public function mount($start, $end)
    {
        $this->start = $start;
        $this->end = $end;
    }

    public function render()
    {
        return view('livewire.date-component')->layout('layout');
    }
}

routes/web.php

<?php

use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('home');
});

Route::get('/date', \App\Livewire\Date::class)->name('date');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment