Livewire で Fomantic-UI のカレンダーを使うには?calendar

ショコラ
ショコラ

Livewire で Fomantic-UI のカレンダーを使うには?calendar

カレンダーのポイントは、wire:ignore を使うところと、カレンダーが消えるタイミングで イベントを発火 するところです。

もっさん先輩
もっさん先輩

手順

Laravel と Livewire をインストールして、Fomantic-UI の カレンダーを使う手順。

  1. プロジェクト名(calendar)を決めて以下のコマンドを実行します。
curl -s https://laravel.build/calendar | bash

インストール時にプロジェクト名のディレクトリが作成されます。

  1. インストールの最後に sudo でパスワードの入力を求められます。

↓下のメッセージが表示されてインストールは終わります。

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them

Get started with: cd calendar && ./vendor/bin/sail up
  1. sail のエイリアスを定義します。
echo "alias sail='[ -f sail ] && sh sail || sh vendor/bin/sail'" >> ~/.bashrc
source ~/.bashrc

Laravel のインストールはここまで。

  1. 「sail up」でコンテナを起動します。
cd calendar && sail up -d
  1. ララベルのトップディレクトリで、Livewireパッケージ をインストールします。
sail composer require livewire/livewire
  1. 次のコマンドを実行して、calendarコンポーネント を生成します。
sail artisan make:livewire calendar
$ sail artisan make:livewire calendar
 COMPONENT CREATED  ?

CLASS: app/Http/Livewire/Calendar.php
VIEW:  resources/views/livewire/calendar.blade.php

次の 2つ のファイルが生成されます。

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class Calendar extends Component
{
    public function render()
    {
        return view('livewire.calendar');
    }
}
<div>
    {{-- The whole world belongs to you. --}}
</div>

※因みに、renderメソッド を定義しなくても livewire.calendar は呼び出されます。

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class Calendar extends Component
{
}
  1. 生成された calendarコンポーネント のクラスとビューを次のように置き換えます。

app/Http/Livewire/Calendar.php

<?php
namespace App\Http\Livewire;
class Calendar extends \Livewire\Component
{
  public $date = '2022-10-25';
  public function dehydrate() {
    \Log::debug($this->date);
  }
}

resources/views/livewire/calendar.blade.php には以下の4つのやり方があります。

① onHide で inputイベント を上げる方法

<div wire:ignore>
  <div class="ui calendar date">
    <div class="ui input left icon">
      <i class="calendar icon"></i>
      <input wire:model="date" id="calendar">
    </div>
  </div>
<script>
$('.calendar.date').calendar({
  type: 'date',
  text: {
    days: ['日','月','火','水','木','金','土'],
    dayNamesShort: ['日','月','火','水','木','金','土'],
    dayNames: ['日曜日','月曜日','火曜日','水曜日','木曜日','金曜日','土曜日'],
    months: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'],
    monthsShort: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'],
    today: '今日',
    now: '今',
    am: '午前',
    pm: '午後'
  },
  formatter: {
    date: 'YYYY-MM-DD'
  },
  onHide:function(val) {
  //document.getElementById('calendar').dispatchEvent(new Event('input'))
    document.querySelector('#calendar').dispatchEvent(new Event('input'))
  }
})
</script>
</div>

ポイントは「wire:ignore」「document.getElementById(‘calendar’).dispatchEvent(new Event(‘input’))」です。id を指定しなければならないので↓下の方法の方が良いです。

wire:focusoutで $set で設定する方法

<div wire:ignore>
  <div class="ui calendar date">
    <div class="ui input left icon">
      <i class="calendar icon"></i>
      <input wire:model="date" wire:focusout="$set('date',$event.target.value)">
    </div>
  </div>
<script>
$('.calendar.date').calendar({
  type: 'date',
  text: {
    days: ['日','月','火','水','木','金','土'],
    dayNamesShort: ['日','月','火','水','木','金','土'],
    dayNames: ['日曜日','月曜日','火曜日','水曜日','木曜日','金曜日','土曜日'],
    months: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'],
    monthsShort: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'],
    today: '今日',
    now: '今',
    am: '午前',
    pm: '午後'
  },
  formatter: {
    date: 'YYYY-MM-DD'
  }
})
</script>
</div>

ポイントは「wire:ignore」「wire:focusout=”$set(‘date’,$event.target.value)”」です。

③ onFocusout@this.set() で設定する方法

<div wire:ignore>
  <div class="ui calendar date">
    <div class="ui input left icon">
      <i class="calendar icon"></i>
      <input wire:model="date" onFocusout="@this.set('date',this.value)">
    <div>
  </div>
<script>
$('.calendar.date').calendar({
  type: 'date',
  text: {
    days: ['日','月','火','水','木','金','土'],
    dayNamesShort: ['日','月','火','水','木','金','土'],
    dayNames: ['日曜日','月曜日','火曜日','水曜日','木曜日','金曜日','土曜日'],
    months: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'],
    monthsShort: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'],
    today: '今日',
    now: '今',
    am: '午前',
    pm: '午後'
  },
  formatter: {
    date: 'YYYY-MM-DD'
  }
})
</script>
</div>

ポイントは「wire:ignore」「@this.set(‘date’,this.value)」です。

onFocusout @this.プロパティ で設定する方法

<div wire:ignore>
  <div class="ui calendar date">
    <div class="ui input left icon">
      <i class="calendar icon"></i>
      <input wire:model="date" onFocusout="@this.date=this.value">
    <div>
  </div>
<script>
$('.calendar.date').calendar({
  type: 'date',
  text: {
    days: ['日','月','火','水','木','金','土'],
    dayNamesShort: ['日','月','火','水','木','金','土'],
    dayNames: ['日曜日','月曜日','火曜日','水曜日','木曜日','金曜日','土曜日'],
    months: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'],
    monthsShort: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'],
    today: '今日',
    now: '今',
    am: '午前',
    pm: '午後'
  },
  formatter: {
    date: 'YYYY-MM-DD'
  }
})
</script>
</div>

ポイントは「wire:ignore」「@this.プロパティ=this.value」です。

  1. resources/views/index.blade.php ファイル を作成します。
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.1/dist/jquery.min.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.0/dist/semantic.min.css">
    <script src="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.0/dist/semantic.min.js"></script>
    <livewire:styles />
  </head>
  <body>
    <div class="ui basic segment">
      <livewire:calendar />
    </div>
    <livewire:scripts />
  </body>
</html>
  1. routes/web.php に Livewireコンポーネント のルートを追加します。
Route::get('/', fn() => view('index'));
  1. ブラウザで確認します。

tail でカレンダーを閉じるタイミングで通信していることを確認しましょう。

tail -f storage/logs/laravel.log

以上

Scroll to Top