Laravel+Inertia.js+Vue.jsでSystemMessagesComponentを作ってみた
こんにちは。
ニシザワです。
本日は、Laravel+Inertia.js+Vue.js3でSystemMessageを出す方法を説明していきます。
今回はSystemMessageをComponent化し、共通のLayoutから自動で出せるようにしていきます。
本ブログではLaravelやInertia.js,Vue.jsのインストール方法は説明しません
Laravel:9
Node.js:18.14
Inertia.js:0.11.x
@inertiajs/inertia-vue3: 0.6.x
TypeScript:4.9
Vue.js: 3.2.x
bulma:0.9.x
メッセージを渡すところです
HandleInertiaRequests.php
shareメソッドで共通の受け渡しが可能です。
今回はmessagesを追加し、type,bodyのオブジェクトとして渡します
computedを使い変更を受け取れるようにしています。
また、今回は5秒で表示を消すようにしたかったため、v-showの値もpropsが更新された時にtrue,falseを切り替えられる様にしました。
usePageで取得できるpropsの値の更新タイミングを拾うところでハマリポイントだったので覚えておくと良いでしょう。
他のところでも使えると思います。
結果としては結構簡潔にかけているのですが、かなり苦労したので参考にしてみてください。
ニシザワです。
本日は、Laravel+Inertia.js+Vue.js3でSystemMessageを出す方法を説明していきます。
今回はSystemMessageをComponent化し、共通のLayoutから自動で出せるようにしていきます。
本ブログではLaravelやInertia.js,Vue.jsのインストール方法は説明しません
環境
PHP:8.1Laravel:9
Node.js:18.14
Inertia.js:0.11.x
@inertiajs/inertia-vue3: 0.6.x
TypeScript:4.9
Vue.js: 3.2.x
bulma:0.9.x
LaravelからSystemMessageをInertia.jsに渡す
Inertia.jsがHandleInertiaRequestsというHTTP Middlewareを用意してくれていますメッセージを渡すところです
HandleInertiaRequests.php
public function share(Request $request): array
{
return array_merge(parent::share($request), [
'auth' => [
'user' => $request->user(),
],
'ziggy' => function () use ($request) {
return array_merge((new Ziggy())->toArray(), [
'location' => $request->url(),
]);
},
'messages' => function () use ($request) {
$messages = [];
foreach ($request->session()->all() as $key => $value) {
if (!str_contains($key, 'message')) {
continue;
}
$messages[] = [
'type' => str_replace('message-', '', $key),
'body' => $value
];
}
return $messages;
}
]);
}
shareメソッドで共通の受け渡しが可能です。
今回はmessagesを追加し、type,bodyのオブジェクトとして渡します
return redirect(route('index'))
->with(['message-success' => '作成しました。']);
return redirect(route('index'))
->with(['message-danger' => '作成に失敗しました。']);
使う側は上記の様になります。
SystemMessagesComponentを作成
SystemMessages.vue
<script lang="ts" setup>
import { computed, ref, watch } from "vue";
import { usePage } from "@inertiajs/inertia-vue3";
const AUTO_REMOVE_MILLISECONDS = 5000;
type MessageType = "success" | "danger" | "info" | "warn";
interface Message {
type: Type;
body: string;
}
export interface Messages {
messages?: Message[];
}
const show = ref<boolean>(true);
const messages = computed<Messages>(() => {
return usePage().props.value.messages as Messages;
});
watch(
() => messages.value,
() => {
show.value = true;
setTimeout(() => {
show.value = false;
}, AUTO_REMOVE_MILLISECONDS);
}
);
</script>
<template>
<div v-show="show" class="system-message">
<div v-for="(message, p) in messages" :key="p">
<article
class="message"
:class="{
'is-success': message.type === 'success',
'is-info': message.type === 'info',
'is-warning': message.type === 'warning',
'is-danger': message.type === 'danger',
}"
>
<div class="message-body">
{{ message.body }}
</div>
</article>
</div>
</div>
</template>
<style lang="scss">
.system-message {
width: 100%;
position: fixed;
bottom: 0;
left: 0;
z-index: 100;
}
</style>
ここでのポイントは同一ページの場合、Inertiaに埋め込まれるpropsが更新されるタイミングで表示したいのでcomputedを使い変更を受け取れるようにしています。
また、今回は5秒で表示を消すようにしたかったため、v-showの値もpropsが更新された時にtrue,falseを切り替えられる様にしました。
usePageで取得できるpropsの値の更新タイミングを拾うところでハマリポイントだったので覚えておくと良いでしょう。
他のところでも使えると思います。
共通Layoutに作成したSystemMessagesComponentを埋め込む
CommonLayout.vue
<script lang="ts" setup>
import SystemMessages from "../Components/SystemMessages.vue";
</script>
<template>
<main class="section">
<slot />
</main>
<SystemMessages />
</template>
最後に共通のLayoutに入れてあげると自動的に、LaravelのControllerからmessageが入ってくると表示されるようになります。結果としては結構簡潔にかけているのですが、かなり苦労したので参考にしてみてください。
- PHP , Laravel , vue.js , Inertia.js