Hi There,
I'm brand new to Vue and Intertia, but I'm trying to convert an existing Laravel project into a Laravel/Vue project as a way to put the Intertai/Vue tutorials into action.
I am trying to build on how flash messages are shown in the Intertia documentation but clearly I am doing something wrong, and probably overcomplicating things.
I have a FlashMessage component:
<script setup>
import { usePage } from '@inertiajs/vue3';
import { computed } from '@vue/reactivity';
import { onMounted, ref } from 'vue';
let show = ref(true);
const props = defineProps({
error : {
type : String,
default: 'bg-red-800'
},
success : {
type : String,
default : 'bg-green-800'
},
notify : {
type :String,
default : 'bg-blue-500'
},
class : {
type : String,
default : ''
}
});
let flash = computed(() => {
if (usePage().props.flash.error) {
return {
message : usePage().props.flash.error,
class : props.class + ' ' + props.error
}
}
else if ( usePage().props.flash.success){
return {
message : usePage().props.flash.success,
class : props.class + ' ' + props.success
}
}
else {
return {
message : usePage().props.flash.notify,
class : props.class + ' ' + props.notify
}
}
});
onMounted(() => {
setTimeout(() => {
show.value = false
},5000);
});
</script>
<template>
<div
v-show="show"
class="text-white fixed bottom-2 lg:bottom-10 right-2 lg:right-10 p-2 lg:p-5 rounded-2xl"
:class="flash.class"
>
{{ flash.message }}
</div>
</template>
which is included in my global layout:
<script setup>
import { Head } from '@inertiajs/vue3';
import Navbar from './Navigation/Navbar.vue';
import FlashMessage from './FlashMessage.vue';
const props = defineProps({
title: {
type : String,
default : null
}
});
</script>
<template>
<div class="bottom-0 fixed">*vue</div>
<Head :title="title ? $page.props.appName + ' - ' + title : $page.props.appName" />
<Navbar v-if="$page.props.auth.user"/>
<main class="text-2xl grid place-items-center h-screen bg-gray-900">
<slot />
</main>
<div v-if="!Object.values($page.props.flash).every(v => v===null)">
<FlashMessage/>
</div>
</template>
and I have added the relevant lines to the HandInterRequests middleware (correctly I hope)
public function share(Request $request): array
{
return array_merge(parent::share($request), [
'appName' => config('app.name'),
'auth.user' => fn () => $request->user()
? $request->user()->only('id', 'name', 'email','streak')
: null,
'flash' => [
'success' => fn () => $request->session()->get('success'),
'error' => fn () => $request->session()->get('error'),
'notify' => fn () => $request->session()->get('notify')
],
]);
}
Then I have a SessionsController where I handle authentication - this was a custom build, not using Breeze or any of the other scaffoldings. I have a store method where I authenticate a user and then forward them to a dashboard, but I want to include a flash message and I'm not sure how:
public function store()
{
$attributes = request()->validate([
'email' => ['required','email'],
'password' => ['required']
]);
if (auth()->attempt($attributes)){
$user = auth()->user();
if ($user->mostRecentTest() && ! (Carbon::parse($user->mostRecentTest()->completed_at)->isToday() || Carbon::parse($user->mostRecentTest()->completed_at)->isYesterday())){
$user->streak = 0;
$user->save();
}
return Redirect::route('topic.index')->with('success', 'Welcome back ' . $user->name);
}
return back()->withErrors(['email' => 'Your provided credentials cannot be verified.']);
}
And lastly my TopicController ```index```` method that shows the dashboard:
public function index()
{
return Inertia::render('Topic/Index',[
'topics' => Auth::check() ? Topic::mine()->orderBy('name')->get() : null
]);
}
This successfully redirects the user to the dashboard but no flash message is shown and using the Vue.js devtools, when I examine the Layout component, all three flash properties are null.
{"success":null,"error":null,"notify":null}
So either I am not setting the flash message or its getting lost in the redirect, or I'm doing something else wrong!
Thanks for any help.