One tiny little problem: I need a single parameter to be carried from a blade view to a vue component, with which the vue component can get data from the database.
Without getting too much into fine details, I just successfully did it. Here is how:
This button group is in a blade view, but I want it to “bring” the reservation ID as a parameter with it upon clicking this orange change reservation button.
1. Click the orange button in index.blade.php
<button
class="mt-1 btn btn-sm btn-custom-warning"
onclick="openReservation({{ $booking->id }})" />
予約変更
</button>
<script>
function openReservation(id) {
// Redirect to the reservation_registration route with the ID parameter
window.location.href = `/reservation-registration/${id}`;
}
</script>
2. Go to web.php
Route::get('/reservation-registration/{id}',
function ($id) {return view('reservation_registration',
['reservationId' => $id]);})->where('id', '[0-9]+');
3. Which displays reservation_registration.blade.php
<x-app-layout>
<!-- Vue.js component -->
<div id="app">
<reservation_registration
:reservation-id="{{ $reservationId ?? 'null' }}">
</reservation_registration>
</div>
</x-app-layout>
4. Go into the reservation_registration.vue component
Yeah, I know kebab-case for html and PascalCase for JavaScript files… but I didn’t make this component. Work with what you got! The important thing here is props.
<script>
import ReservationForm from './ReservationForm.vue';
import axios from 'axios';
export default {
props: {
reservationId: {
type: Number,
required: true
}
},
components: {
ReservationForm,
},
mounted() {
console.log("Reservation ID:", this.reservationId);
this.fetchReservationData();
},
methods: {
async fetchReservationData() {
try {
const response = await axios.get
(`/api/fetch-reservation-data/${this.reservationId}`);
const booking = response.data;
// Map the API response to `reservationData` fields
// expected by the form
this.reservationData = {
id: booking.id,
reservationName: booking.reserver_name,
guestName1: booking.guest_name_1,
...
};
} catch (error) {
console.error("can't find the data", error);
}
},
The mounted method effectively retrieves data, and as you can see, it uses the props parameter number reservationID.
5. When fetchReservationData() is called, make an API call to routes/api.php
php artisan install:api
This is needed, at least in Laravel 11, but you can remove some of the stuff it comes with.
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ReservationRegistrationController;
Route::get('/fetch-reservation-data/{id}',
[ReservationRegistrationController::class,
'fetchReservationData']);
6. Jump into the back end ReservationRegistrationController.php and run the fetchReservationData() method
This uses the $id parameter to get and return all the Booking data from the database.
use App\Models\Booking;
class ReservationRegistrationController extends Controller
{
public function fetchReservationData($id)
{
$booking = Booking::with(['room', 'staff'])->find($id);
if (!$booking) {
return response()->json(['message' => '予約が見つかりませんでした。'], 404);
}
return response()->json($booking);
}
}
7. Map the returned json($booking) response to correctly align with form fields, as seen already in reservation_registration.vue
methods: {
async fetchReservationData() {
try {
const response = await axios.get
(`/api/fetch-reservation-data/${this.reservationId}`);
const booking = response.data;
// Map the API response to `reservationData` fields
// expected by the form
this.reservationData = {
id: booking.id,
reservationName: booking.reserver_name,
guestName1: booking.guest_name_1,
...
};
} catch (error) {
console.error("can't find the data", error);
}
},
8. Now reservation_registration.vue is the parent to RegistrationForm.vue
<template>
<div class="page-container">
<div class="main-content">
<div class="form-container">
<ReservationForm
:reservationData="reservationData"
:rooms="filteredRooms"
:isEditMode="isEditMode"
:bookings="bookings"
@submit="handleSubmit"
@filter="applyFilters"
@cancel-edit="handleCancelEdit"
/>
</div>
</div>
</div>
</template>
<script>
import ReservationForm from './ReservationForm.vue';
import axios from 'axios';
export default {
props: {
reservationId: {
type: Number,
required: true
}
},
components: {
ReservationForm,
},
data() {
return {
reservationData: {
id: null, // 追加: 編集時の予約 ID を保持するためのフィールド
reservationName: '',
guestName1: '',
...
};
},
9. Lastly, the child RegistrationForm.vue
You can see the form inputs use v-model to bind each form field to its corresponding property in reservationData and creates a two-way binding:
• If reservationData.reservationName changes in the component’s data, the input field will automatically reflect this change.
• Likewise, any user input in the field updates reservationData.reservationName in real time.
<template>
<form @submit.prevent="handleSubmit" class="reservation-form">
<div class="form-group">
<label for="reservationName">予約者名:</label>
<input type="text" id="reservationName"
v-model="reservationData.reservationName" class="compact-input">
</div>
<div class="form-group">
<label for="guestName1">宿泊者名:</label>
<input type="text" id="guestName1"
v-model="reservationData.guestName1" class="compact-input">
</div>
So if and when fetchReservationData() successfully retrieves data, it assigns values to reservationData fields based on the API response.
It really does help my to think about what one of my first mentors said in regards to programming, “It’s just a bunch of tiny little problems… if you can’t figure it out, break it into even smaller pieces.”
It also would help if I learned JavaScript.