☆Yuus Memo☆
非エンジニアの方でも業務を効率化できるプログラムを紹介します!
Laravel

Laravel + Vue.jsでGoogleカレンダーのクローンを作ろう!!【Laravel8対応】フロントエンド編①

皆さんこんにちは!!
昨日に引き続き、フロント(Vue.js)側の開発を始めていきます。

前回までで、一応LaravelのBlade上にVue.jsのコンポーネントを表示する事ができました。
今回はカレンダーを作っていきたいと思います!

今回は前回インストールしておいたライブラリーを使用するので、それの使い方も併せて解説していきます。

ホーム画面を用意する

それでは早速始めます。
本当は難しい事はせずに ExampleComponent.vueへ書いて行っても良いのですが、実際の開発では複数のコンポーネントが複雑に絡み合って1つのページを作っていきます。

今回は画面が少ないので、複雑にはならないので安心して下さい。

app.jsの編集

現在の「app.js」は次の様な内容だと思います。

require('./bootstrap');

window.Vue = require('vue').default;

Vue.component('example-component', require('./components/ExampleComponent.vue').default);

const app = new Vue({
    el: '#app',
});

resources/js/app.jsを開き次の様に変更して下さい。

import Vue from 'vue'
import Vuetify from 'vuetify';
import Home from "./components/pages/HomeComponent";

require('./bootstrap');

Vue.component('HomeComponent', require('./components/pages/HomeComponent.vue').default);
Vue.use(Vuetify);

const app = new Vue({
    el: '#app',
    vuetify: new Vuetify(),
    components: {
        Home
    }
});

components/pages/HomeComponent.vueはまだ作成していませんが、次に作ります。
今回の開発のメインコンポーネントです。

簡単に説明します。

最初のImport文で、Vue.jsとvuetifyを利用することを宣言しています。
HomeComponent.vueもImportしていますが、まだ作成していないので今の段階ではエラーになります。

Vue.component(‘HomeComponent’, require(‘./components/pages/HomeComponent.vue’).default);
Vue.use(Vuetify);

この文でHomeComponentの使用とVuetifyを使用することを宣言しています。
あとはconst app = new Vue({〜の部分で、マウントする要素などを宣言しています。

Vuetifyとは?

Vue.jsのUIライブラリーです。Googleが提唱したマテリアルデザインにのっとっており、直感的で使いやすいコンポーネントを利用することができます。

デザインの知識が全く無くても、綺麗なUIが作成できます。

Vuetifyは今回使用するUI以外にも数多くの素敵なUIが使用できます。

こちらからご確認ください。

公式ドキュメント

LaravelのBladeファイル(Top画面の編集)

今回は楽をして、「resources/views/home.blade.php」を使用します。
手を抜いてすみません(笑)

home.blade.phpを次の様に編集して下さい。

@extends('layouts.app')

@section('content')
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-12">
                <div class="card">
                    <div class="card-header text-center">My Scheduler</div>

                    <div class="card-body">
                        <!--ここにカレンダーを表示します。-->
                        <div id="app">
                            <home-component></home-component>
                        </div>
                        <!--ここまで-->
                    </div>
                </div>
            </div>
        </div>
    </div>
@endsection

前回 ExampleComponentを使用した時と同じで、コンポーネント名をスネークケースにしたものをHTMLタグの様に記述します。

この作業に関しては、特別説明は要らないと思いますので次に進みます。

Web.phpの編集

Laravel側のページはほとんど利用しませんが、Home画面はLaravelのBladeを利用するので次の様に編集して下さい。

「routes/web.php」というファイルになります。

<?php

use Illuminate\Support\Facades\Route;

Auth::routes();

Route::get('/', [App\Http\Controllers\HomeController::class, 'index'])->name('home');

基本的にルートにアクセスしたら、ホーム画面を表示する様にしているだけです。
Auth::routes();
という行がありますが、「Laravel/ui」の機能で、この機能のおかげでユーザー管理機能が自動で作成されています。

もう一つファイルを編集します。
「app/Providers/RouteServiceProvider.php」を開いて下さい。
このファイルを次の様に編集して下さい。

RouteServiceProvider.phpの「public const HOME = ‘/’;」でリダイレクト先をドメイン直下へ変更します。

class RouteServiceProvider extends ServiceProvider
{
    /**
     * The path to the "home" route for your application.
     *
     * This is used by Laravel authentication to redirect users after login.
     *
     * @var string
     */
    public const HOME = '/';

// 省略

アクセスを受けた際に、ログインしていなければ、ログイン画面へリダイレクトしてくれます。
ログイン後は自動でHome(’/’)へリダイレクトします。

Vue.jsのコンポーネントを格納するディレクトリを用意する

では、ターミナルを開き次のコマンドを実行してディレクトリとファイルを用意して下さい。

MACやWINDOWSで開発している方は、GUIでフォルダを作成しても大丈夫です。

my-calendar $ mkdir resources/js/components/pages
my-calendar $ mkdir resources/js/components/pageParts
my-calendar $ mkdir resources/js/components/form

my-calendar $ touch resources/js/components/pages/HomeComponent.vue 
my-calendar $ touch resources/js/components/pageParts/Calendar.vue

カレンダーの作成

準備ができたので、イベントを表示するカレンダーを作成します。

resources/js/components/pageParts/Calendar.vueを開き、次の様に記述して下さい。

<template>
    <div>
        <v-sheet height="100vh">
            <v-calendar></v-calendar>
        </v-sheet>
    </div>
</template>

<script>
export default {
    name: 'Calendar',
};
</script>

Vuetifyが提供する<v-calendar>コンポーネントを使用します。

v-calendar コンポーネントは、日、週、月、またはカテゴリビューで情報を表示するために使用されます。 daily ビューには、すべての日または時間の要素のためのスロットがあり、weeklyとmonthlyのビューには、それぞれの日のスロットがあります。 カテゴリビューには、指定されたカテゴリまたは指定されたイベントのカテゴリに基づいて、その日の各カテゴリのためのスロットと時間指定されたセクションがあります。 必要に応じて、イベントの配列を渡すことができ、それらは適切な日時にレンダリングされます。

https://vuetifyjs.com/ja/components/calendars/

<v-calendar>コンポーネントについて詳しく知りたい方はこちらをご覧ください。
サンプルなども用意されていますので、1度目を通されると良いと思います。

Calendars


続いて、resources/js/components/pages/HomeComponent.vueを開き、次の様に記述して下さい。

<template>
    <v-app id="app">
        <Calendar />
    </v-app>
</template>

<script>
import Calendar from '../pageParts/Calendar';

export default {
    components: {
        Calendar,
    },
    mounted() {
        console.log('HomeComponent mounted.');
    },
};
</script>

<style>
#app {
    font-family: Avenir, Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
    color: #2c3e50;
}
</style>

これでカレンダーを表示する部分ができました。

ここでポイントなのは、Vuetifyを使用するために全体の要素を<v-app>で全体を囲う必要があるという事です

<v-app></v-app>で囲った中でVuetifyのコンポーネントを使用することができます。

「import Calendar from ‘../pageParts/Calendar’;」の部分でCalendarコンポーネントを読み込み、

components: {
        Calendar,
    },

でCalendarコンポーネントを使用する事を宣言しています。
使用している箇所は、

<v-app id="app">
        <Calendar />
    </v-app>

です。
簡単ですよね。

このままではVuetifyのスタイルを適用できていないので、スタイルを適用しておきます。

resources/sass/app.scssを開き次の様に編集して下さい。

// Fonts
@import url('https://fonts.googleapis.com/css?family=Nunito');

// Variables
@import 'variables';

// Bootstrap
@import '~bootstrap/scss/bootstrap';

// Vuetify
@import '~vuetify/dist/vuetify.min.css';
@import '~@mdi/font/css/materialdesignicons.min.css';

準備編でインストールしておいたファイルやアイコンなどを利用できるようにします。

次にターミナルで、次のコマンドを実行して下さい。

my-calendar $ npm run dev

# 次の表示が出ればOK
webpack compiled successfully

php artisan serveでローカルサーバーを立ち上げて「http://localhost:8000」へアクセスして下さい。

ログイン画面へ飛ぶと思いますので、ログインしてみて下さい。

素敵なデザインのカレンダーが表示されました!!
たったこれだけのコードで、カレンダーが作れます。

カレンダーにイベントを表示してみる

いよいよ、Laravelと連携してイベントを表示してみたいと思います。
resources/js/components/pageParts/Calendar.vueを次の様に変更して下さい。

<template>
    <div>
        <v-sheet height="100vh">
            <v-calendar
                v-model="value"
                :events="events"
                @change="fetchEvents"
            ></v-calendar>
        </v-sheet>
    </div>
</template>

<script>
export default {
    name: 'Calendar',
    data: () => ({
        value: new Date('2021/09/01'), // 表示する月を指定 ※予めイベントデータを作成しておいて下さい。
        events: [],
    }),
    methods: {
        fetchEvents() {
            axios.get('/api/events')
                .then(response => {
                    this.events = response.data;
                })
                .catch(error => {
                    console.error(error);
                });
        }
    }
};
</script>

:eventsにはLaravelのコントローラから返却されたイベントデータをバインドしています。

@changeにはLaravelへAPIリクエストを投げるfetchEventsアクションを指定します。
こうすることでカレンダーに予定が表示されます。

変更したら、ターミナルで「npm run dev」を実行して変更を適用して下さい。

Vue.jsの基本構文を補足

data: () => ({
        value: new Date('2021/09/01'), // 表示する月を指定 ※予めイベントデータを作成しておいて下さい。
        events: [],
    }),

dataで定義した変数はtemplateブロックでは{{ 変数 }}のように書くことでその値を表示することができます。
今回は変数を直接要素にバインドしました。

 v-model="value"
 :events="events"

v-bind は 変数 を HTML コンポーネントに反映(出力)します。HTML コンポーネントの値が変わっても、変数 の値は変わりません。Vue.js から HTML への一方通行です。

一方、v-model は 変数と HTMLの双方向に影響します。 HTML コンポーネントの値に変更があった場合、自動で Vue.js側の変数 の値を更新します。

:eventsは、v-bindの省略記法です。

詳しくはこちらをご覧ください。

フォーム入力バインディング

@change="fetchEvents"

は、イベントをハンドリングしています。
今回はvalue(表示する月を指定)のチェンジイベントを補足しています。

一度公式ドキュメントを除いてみて下さい。


それでは、ローカルサーバーを立ち上げてブラウザーで確認してみましょう!!

画像の様にイベントが表示されましたか?
Laravelのコントローラーを呼び出しているのは次の部分になります。

fetchEvents() {
            axios.get('/api/events')
                .then(response => {
                    this.events = response.data;
                })
                .catch(error => {
                    console.error(error);
                });
        }

axiosというライブラリーを利用して、「routes/api.php」で設定したルートへGETリクエストを送信しています。

返却されたデータを、

data: () => ({
        value: new Date('2021/09/01'), // 表示する月を指定 ※予めイベントデータを作成しておいて下さい。
        events: [],
    }),

で宣言したeventsという変数へ代入しています。
Vuetifyのカレンダーは、次の様に指定するだけで、変数に変更があると反映してくれます。

<v-calendar
                v-model="value"
                :events="events"
                @change="fetchEvents"
            ></v-calendar>

本当に便利ですね!!

axiosとは

axiosとはブラウザやnode.js上で動くPromiseベースのHTTPクライアントです。
jQueryで言うところのjQuery.ajaxです。
非同期にHTTP通信を行いたいときに容易に実装できます。
Vue.jsでは非同期通信を行うのにaxiosを使うのがスタンダードとなっております。

Laravelではプロジェクトを作成した時に一緒にインストールされているので、特別な設定をする必要無く使用する事ができます。

axiosについて詳しく知りたい方はこちらをご覧ください。

https://axios-http.com/

フロント編①のまとめ

お疲れ様でした!!
いかがだったでしょうか?あまりに簡単にLaravelとVue.jsが連携できたので拍子抜けしているのではないでしょうか?

今回は、取り敢えず表示を見たかったので、コンポーネントに直接APIとの通信を書きましたが、複数のコンポーネントでイベントデータを利用したいので、次回から、「Vuex」を使用して状態管理を実装していきたいと思います。

Vuexは苦手意識を持っている方が非常に多いのですが、とても便利なものなので、頑張って覚えていきましょう!!

最後までお読みいただきありがとうございました!!次回もお楽しみに!!

以前紹介しましたが、下記の書籍で「Vue.jsを利用してGoogleカレンダーのクローン」を作成しています。

Vue.jsの書籍で現在、最もおすすめできる書籍です。
よければ読んでみてください!

コメントを残す