laravel / precognition

Anticipate the outcome of a future HTTP request.
https://laravel.com/docs/precognition
MIT License
123 stars 31 forks source link

Request errors never get set on form #82

Closed ncphillips closed 4 weeks ago

ncphillips commented 1 month ago

Laravel Precognition Plugin Version

0.5.6

Laravel Version

10.48.10

Plugin

Vue w/ Inertia

Description

Validation requests are sent to the server, which responds with the appropriate errors and HTTP status 422.

The errors are visible in the network tab, but they are never set on the Form object itself.

Steps To Reproduce

I'm trying to setup precognition with Vue + Inertia.

The request is being made and the errors are being returned, but it's not populating the form's errors object. It remains as an empty object.

web.php

Route::name('store')
    ->post('/', [CourseAssignmentController::class, 'store'])
    ->middleware([HandlePrecognitiveRequests::class]);

Controller Method Signature

public function store(CreateAssignmentRequest $request)

CreateAssignmentRequest

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class CreateAssignmentRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'title' => 'required|string',
            'overview' => 'string|nullable',
        ];
    }
}

Vue Component

import {useForm} from 'laravel-precognition-vue-inertia';

const form = useForm('post', route('courses.assignment.store', {course: props.course.id}), {
  title: '',
  overview: '',
});

function createAssignment() {
  form.submit({
    preserveScroll: true,
    onSuccess: () => form.reset(),
  });
}
ncphillips commented 1 month ago

What kind of more info would need @driesvints, @timacdonald ? I could try to get a test app to reproduce, send a loom, or hop on a call.

timacdonald commented 1 month ago

It would be good to see the entire Vue file and a reproduction repository would be even better. I'm unable to reproduce the issue with what I can see here.

driesvints commented 1 month ago

@ncphillips try reproducing the issue on a fresh repo so Tim can have a better look. Thanks!

laravel new bug-report --github="--public"
ncphillips commented 1 month ago

Interesting! I'll see what I can do.

I feel our setup must have some assumed thing setup incorrectly

timacdonald commented 1 month ago

Thanks, @ncphillips. Keen to help out where we can to get this sorted for ya.

Let us know how you go.

ncphillips commented 1 month ago

I haven't had any luck :( I spun a new app up and everything worked fine.

I went back and made sure to upgrade all the inertia, precognition, axios, etc.

I feel like the most likely culprit is our version of laravel ? Really not sure.

I'm not entirely sure how to spin up a laravel 10

timacdonald commented 1 month ago

I don't believe there has been any changes to the framework's precognition code since 10.11.0.

Could you provide the full vue file you are having issues with?

Do you have any global configuration that could be impacting this?

timacdonald commented 1 month ago

@ncphillips, I'm gonna close this one. I'm certainly up for helping get to the bottom of it. If you can share any more information we can keep digging in.

ncphillips commented 1 month ago

That's fair @timacdonald, thanks!

ncphillips commented 1 month ago

Okay I just tried again from scratch.

Here's the JS package version I got

"laravel-precognition-vue-inertia": "^0.5.6",

I just whipped up a brand new page with this Vue template:

<template>
  <form @submit="submit">
    <label>
      Name:
      <input id="name" label="Name" v-model="form.name" @change="form.validate('name')" />
      <span v-if="form.errors.name">{{ form.errors.name }}</span>
    </label>
    <button type="submit" :disabled="form.processing">Submit</button>
    <div v-if="form.validating">Validating</div>
    <div v-if="form.submitting">Submitting</div>
    <div>
      <pre><data>{{ JSON.stringify(form.errors) }}</data></pre>
    </div>
  </form>
</template>
<script setup lang="ts">
import {useForm} from 'laravel-precognition-vue-inertia';

const form = useForm('post', '/banana', {
  name: '',
});

const submit = () =>
  form.submit({
    preserveScroll: true,
    onSuccess: () => form.reset(),
  });
</script>

These are the routes in my web.php:

Route::get('banana', function () {
    return inertia('Banana');
});

Route::post('banana', function (\App\Http\Requests\BananaRequest $request) {
    return redirect()->back()->with('success', 'Hooray!');
})->middleware([HandlePrecognitiveRequests::class]);

Here is the Request

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class BananaRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
     */
    public function rules(): array
    {
        return [
            'name' => 'required|min:3'
        ];
    }
}

I do notice that it installed a different version of axios

image

But once again, I see that it is returning with a 422 and the error messags, but those error messags are not in my form

image
timacdonald commented 1 month ago

I copied this all verbatim into a fresh Laravel breeze application using Laravel 10.48.10 and Precognition 0.5.6 and everything seems to be working as expected.

https://github.com/user-attachments/assets/5f9b96c1-d57b-46c5-9282-8bfec7830580

Couple more things I'd love to know:

I'm also wondering if you are doing any global configuration in this application that could be impacting this somehow?

ncphillips commented 1 month ago

I copied this all verbatim into a fresh Laravel breeze application using Laravel 10.48.10 and Precognition 0.5.6 and everything seems to be working as expected.

Me too, it's really weird. I absolutely think it's something to do with our setup. This app's been around a while and has some unconventional things going on in various places.

Could you please share the response headers?

image

Are there any messages in the JS console?

I'm seeing some cookie warnings. However, I also see them when I submit the form, which works just fine.

image

Do you have any special CORS configuration?

I am not aware of any special CORS config. Also, I do seem to be getting a valid response? Unless 422 is not what precognition expects.

I'm also wondering if you are doing any global configuration in this application that could be impacting this somehow?

Maybe. But I can't think of what it might be.

ncphillips commented 4 weeks ago

Progress!

image

Our errors are wrappe din another layer of data.

I suspect we have a middleware that wraps all json responses in data

ncphillips commented 4 weeks ago

BOOM

image

We are in the process of moving form a SPA to Inertia. For the SPA we have a custom ExceptionHandler that wraps any thrown exceptions into a palatable data structure.

I just needed to throw a little isPrecognition() check in that thing to get it working!

image
timacdonald commented 3 weeks ago

This is great! Glad to hear you were able to get this working and thanks for the update.

Hope you enjoy the package!

ncphillips commented 3 weeks ago

Looks great so far! I think my only complaint is useForm returns any. Might look at contributing an improvement there