0

I'm quickly becoming confident in Laravel, but this one has me stumped. I've successfully created a number of forms that validate and save the data before moving to a new page, but this one is just refreshing the page and I can't see why.

I'd like the dashboard page to ask the user for a date, then display available bookings for that date in the bookings.index page.

dashboard.blade.php includes:

<form method="POST" action="{{ route('bookings.index') }}">
    @csrf

    <!-- Select Date -->
    <div>
        <x-input-label for="date" :value="__('Date')" />

        <x-text-input id="date" class="block mt-1 w-full" type="date" name="date" :value="old('date')" required autofocus />

        <x-input-error :messages="$errors->get('date')" class="mt-2" />
    </div>
    <div>
        <x-primary-button class="ml-3">
            {{ __('Find Available Fields') }}
        </x-primary-button>
    </div>
</form>

Booking Controller includes:

<?php

namespace App\Http\Controllers;

use App\Model\User;
use App\Models\Booking;
use App\Models\Field;
use App\Models\Timeslot;
use Carbon\CarbonPeriod;
use Illuminate\Http\Request;

class BookingController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $validated = $request->validate([
            'date'    => 'required|date|after:yesterday',
        ]);

        redirect(route('bookings.index', [
            'fields' => Field::get(),
            'timeslots' => Timeslot::get(),
            'date' => $request->date,
        ]));
    }
}

web.php includes:

Route::get('/dashboard', function () {
    return view('dashboard', [
        'fields' => Field::get(),
        'timeslots' => Timeslot::get(),
        'bookings' => auth()->user()->bookings(),
    ]);
})->middleware(['auth', 'verified'])->name('dashboard');
Route::resource('bookings', BookingController::class)
    ->only(['index', 'store', 'edit', 'update', 'destroy'])
    ->middleware(['auth', 'verified']);

When I enter a date and click on the 'Find Available Fields' button, I expect to be sent to the bookings/index page, but instead the dashboard page refreshes. I can't see anything in the above code that would cause that, so I wonder if I need to look somewhere else. Any guidance would be greatly appreciated.

Edit: Since the submit request never reaches the bookings/index page, I'm including the actual source code of the form. Again, it looks good to me so I don't know why the controller code isn't triggering.

    <form method="POST" action="http://localhost:8000/bookings">
        <input type="hidden" name="_token" value="NTw8hEadjvDv0HIlYDSZNmFFi0e6U9O9UzxfRy13">
        <!-- Select Date -->
        <div>
            <label class="block font-medium text-sm text-gray-700" for="date">Date</label>
            <input  class="rounded-md shadow-sm border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 block mt-1 w-full" id="date" type="date" name="date" required="required" autofocus="autofocus">
                        </div>
        <div>
            <button type="submit" class="inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 active:bg-gray-900 focus:outline-none focus:border-gray-900 focus:ring ring-gray-300 disabled:opacity-25 transition ease-in-out duration-150 ml-3">Find Available Fields</button>
        </div>
    </form>
maganthro
  • 361
  • 1
  • 3
  • 10

1 Answers1

1

This is because of a wrong redirect syntax(also you need to pass a return keyword). To redirect to a named route, you can't pass it as a parameter in the redirect() helper. Rather you should do it this way:

return redirect()->route('my.route');

or simply to_route('my.route');

You can also pass your variables as a second parameter to these helpers.

That said, change your booking controller code to this:

<?php

namespace App\Http\Controllers;

use App\Model\User;
use App\Models\Booking;
use App\Models\Field;
use App\Models\Timeslot;
use Carbon\CarbonPeriod;
use Illuminate\Http\Request;

class BookingController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $validated = $request->validate([
            'date'    => 'required|date|after:yesterday',
        ]);

        return redirect()->route('bookings.index', [
            'fields' => Field::get(),
            'timeslots' => Timeslot::get(),
            'date' => $request->date,
        ]);
    }
}

For more info, take a look at the docs

After further discussion and research, the primary problem is that the form was set to 'POST' while an index page requires the 'GET' method. Check this answer.

maganthro
  • 361
  • 1
  • 3
  • 10
Innovin
  • 776
  • 1
  • 5
  • 19
  • You're correct about my typo, but unfortunately, that's not the main problem. I don't think the page is ever reaching the BookingController's index function. If I do a dd('Booking.index') at the top of the function and navigate directly to the page, it shows the dd content. When I submit the form from Dashboard, it just reloads the same page. – maganthro Nov 10 '22 at 18:36
  • Just to be sure, I have now researched laravel logs and added a debug log that appears if I go direct to the page, but doesn't appear if I try to submit the form from Dashboard. – maganthro Nov 10 '22 at 18:48
  • @maganthro From your code, the form data is submitted to the ```route('bookings.index')``` which is handled by your controller ```index``` function which in turn redirects to the same ```route('bookings.index')``` with some data. So basically, all your code does is reload the same page with some data after the form is submitted. – Innovin Nov 10 '22 at 18:52
  • but the bookings.index page never loads. it always goes back to dashboard.index. – maganthro Nov 10 '22 at 18:56
  • That's quite a very weird behaviour – Innovin Nov 10 '22 at 18:58
  • I think there must be a problem with how I'm handling the dashboard, since I never had a problem before that. Thanks for your help and responding so quickly. I'm still working through this. – maganthro Nov 10 '22 at 18:59
  • I"ve updated the web.php in the original post in case that sparks something. – maganthro Nov 10 '22 at 19:00
  • 1
    The error can't be from your dashboard route since the dashboard page loads fine. I think the problem is from your input validation in index controller. If a validation fails, laravel redirects back to the previous page with error messages. Try this : in your dashboard blade file ```@if($errors->any()) @foreach($errors->all() as $error) {{ $error }}
    @endforeach @endif ``` and tell me what you see
    – Innovin Nov 10 '22 at 19:05
  • Now that's interesting. Yes, I get errors from the validation in the booking.store method. Why would it be going to 'store'? – maganthro Nov 10 '22 at 19:10
  • Perhaps it's because of the ```Resource``` route. I'm not so familiar with ```Route::resource()```. Perhaps you could just define a route group instead. – Innovin Nov 10 '22 at 19:14
  • 1
    I just read the docs. For a route resource. If it is a ```POST``` request ```/bookings```, the request is sent to the ```store()``` controller function. If it is a ```GET``` request, that is only when it is sent to the ```index()``` controller function. Check [this answer](https://stackoverflow.com/questions/23505875/laravel-routeresource-vs-routecontroller) . – Innovin Nov 10 '22 at 19:18
  • That was it. I've had so many errors telling me I must use POST, not GET (even when I've been using POST), it's strange that I didn't get one telling me the other way around. I generally avoid GET, and thought it would try to include the classes in the URI, but apparently not. It's all good now. Thanks for your help. I'll edit your original response and accept it. – maganthro Nov 10 '22 at 19:37
  • Alright. Glad I could help :) – Innovin Nov 10 '22 at 19:40