Coder Social home page Coder Social logo

laravel / precognition Goto Github PK

View Code? Open in Web Editor NEW
96.0 5.0 24.0 320 KB

Anticipate the outcome of a future HTTP request.

Home Page: https://laravel.com/docs/precognition

License: MIT License

JavaScript 36.09% TypeScript 63.45% Shell 0.46%
laravel

precognition's Introduction

Laravel Precognition

Test Status Build Status Total Downloads Latest Stable Version License

Introduction

Laravel Precognition allows you to anticipate the outcome of a future HTTP request. One of the primary use cases of Precognition is the ability to provide "live" validation in your frontend application.

Official Documentation

Documentation for Laravel Precognition can be found on the Laravel website.

Contributing

Thank you for considering contributing to Laravel Precognition! The contribution guide can be found in the Laravel documentation.

Code of Conduct

In order to ensure that the Laravel community is welcoming to all, please review and abide by the Code of Conduct.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

License

Laravel Precognition is open-sourced software licensed under the MIT license.

precognition's People

Contributors

dij-qhoekman avatar driesvints avatar jessarcher avatar nunomaduro avatar taylorotwell avatar timacdonald avatar yo-goto avatar zhanang19 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

precognition's Issues

Module not found when build SSR with laravel inertia react

Laravel Precognition Plugin Version

0.3.2

Laravel Version

10.14.1

Plugin

React w/ Inertia

Description

No issue using client side. But in SSR, I found this problem when using the package.
I just install fresh laravel with inertia-react as test project then install the precognation

See below :

Inertia SSR server started.
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/hendi/Sites/testing/node_modules/laravel-precognition/dist/client' imported from /Users/hendi/Sites/testing/node_modules/laravel-precognition/dist/index.js
    at new NodeError (node:internal/errors:399:5)
    at finalizeResolution (node:internal/modules/esm/resolve:326:11)
    at moduleResolve (node:internal/modules/esm/resolve:945:10)
    at defaultResolve (node:internal/modules/esm/resolve:1153:11)
    at nextResolve (node:internal/modules/esm/loader:163:28)
    at ESMLoader.resolve (node:internal/modules/esm/loader:838:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:424:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:77:40)
    at link (node:internal/modules/esm/module_job:76:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

Steps To Reproduce

Here i just done

Provide support for interfaces for useForm function (Vue & Inertia)

Currently "useForm" from InertiaJS library support to pass a interface as generic, however "useForm" from "laravel-precognition-vue-inertia" only allows to pass a type that extends Record<string, unknown>. The fact to useForm uses a different signature it will force to convert all the form interfaces into types.

Using the keyword "satisfies" will solve the problem, however the linter will not suggest the interface properties.

It can be a good idea to support interfaces so it can facilitate the migration for InertiaJS useForm to Laravel Precognition useForm.

Make initial value (third parameter of useForm) dynamic

Like for the method and url, it would be helpful to have also initial value originated by function.

Example are:

  • initial function is created looking at a computed property values (fetched asynchronously from backend)
  • when you create any object and you use same component for creation or editing (component is not refreshed on success).
  • if you watch any dinamic variable to trigger form reset (typeing search values should reset the query cursor for example).

Thank you.

Transform data before validation

On our form we use the inertia form transform() method to transform some fields before posting (i.e. a datepicker field which return an object into a relevant string). Is there anyway we can transform a field before validating it?

form.validating always false

Laravel Precognition Plugin Version

0.5.1

Laravel Version

10.22

Plugin

Vue w/ Inertia

Description

I can't see form.validating change while validating

Steps To Reproduce

<input v-model="form.first_name" @change="form.validate('first_name')" />
 --- {{ form.validating }} ---
const form = useForm('post', '/my-route', {
 first_name: null
})

Error: Did not receive a Precognition response

Laravel Precognition Plugin Version

0.3.2

Laravel Version

10.8

Plugin

React

Description

The following function is throwing an error:

const validatePrecognitionResponse = (response) => {
    if (response.headers?.precognition !== 'true') {
        throw Error('Did not receive a Precognition response. Ensure you have the Precognition middleware in place for the route.');
    }
};

image

Even though it is present as a header when inspecting the network tab:

image

Steps To Reproduce

Copied React example from Laravel documentation

`laravel-precognition-vue-inertia` causes compilation errors with Inertia.js Vue 3 Composition API + TS

Laravel Version

10.10

PHP Version

8.2

Database Driver & Version

MySQL Mac

Description

I'm currently working on a Laravel project with Inertia.js Vue 3 Composition API and TypeScript. However, I've encountered an issue after installing and configuring laravel-precognition-vue-inertia. When I run my project, I see several errors in the terminal related to missing exports and modules in laravel-precognition. Here are the errors that I am seeing:

ERROR in ./node_modules/laravel-precognition-vue-inertia/dist/index.js 20:8-32
export 'toSimpleValidationErrors' (imported as 'toSimpleValidationErrors') was not found in 'laravel-precognition' (module has no exports)

ERROR in ./node_modules/laravel-precognition-vue/dist/index.js 29:22-37
export 'createValidator' (imported as 'createValidator') was not found in 'laravel-precognition' (module has no exports)

ERROR in ./node_modules/laravel-precognition-vue/dist/index.js 44:22-46
export 'toSimpleValidationErrors' (imported as 'toSimpleValidationErrors') was not found in 'laravel-precognition' (module has no exports)

ERROR in ./node_modules/laravel-precognition-vue/dist/index.js 91:19-30
export 'resolveName' (imported as 'resolveName') was not found in 'laravel-precognition' (module has no exports)

ERROR in ./node_modules/laravel-precognition-vue/dist/index.js 129:19-25
export 'client' (imported as 'client') was not found in 'laravel-precognition' (module has no exports)

ERROR in ./node_modules/laravel-precognition/dist/index.js 1:0-34
Module not found: Error: Can't resolve './client' in 'project-x/node_modules/laravel-precognition/dist'
Did you mean 'client.js'?
BREAKING CHANGE: The request './client' failed to resolve only because it was resolved as fully specified
(probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '.mjs' file, or a '.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.
Did you miss the leading dot in 'resolve.extensions'? Did you mean '[".",".wasm",".mjs",".js",".jsx",".json",".ts",".tsx",".vue"]' instead of '["",".wasm",".mjs",".js",".jsx",".json",".ts",".tsx",".vue"]'?

ERROR in ./node_modules/laravel-precognition/dist/index.js 2:0-85
Module not found: Error: Can't resolve './validator' in 'project-x/node_modules/laravel-precognition/dist'
Did you mean 'validator.js'?
BREAKING CHANGE: The request './validator' failed to resolve only because it was resolved as fully specified
(probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '.mjs' file, or a '.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.
Did you miss the leading dot in 'resolve.extensions'? Did you mean '[".",".wasm",".mjs",".js",".jsx",".json",".ts",".tsx",".vue"]' instead of '["",".wasm",".mjs",".js",".jsx",".json",".ts",".tsx",".vue"]'?

ERROR in ./node_modules/laravel-precognition/dist/index.js 3:0-24
Module not found: Error: Can't resolve './types' in 'project-x/node_modules/laravel-precognition/dist'
Did you mean 'types.js'?
BREAKING CHANGE: The request './types' failed to resolve only because it was resolved as fully specified
(probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '.mjs' file, or a '.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.
Did you miss the leading dot in 'resolve.extensions'? Did you mean '[".",".wasm",".mjs",".js",".jsx",".json",".ts",".tsx",".vue"]' instead of '["",".wasm",".mjs",".js",".jsx",".json",".ts",".tsx",".vue"]'?`

laravel-precognition-vue-inertia - useForm redirect behaviour

Laravel Precognition Plugin Version

0.4.1

Laravel Version

10.17.1

Plugin

Vue w/ Inertia

Description

When calling form.submit(), the controller is correctly hit, and a redirect response is returned using to_route() within the controller.

Inspecting the network tab, a request is fired off to get the redirected page, however rather then a partial request being returned, the full HTML is returned and the redirect never actually happens.

Steps To Reproduce

Component

<script setup lang="ts">
import { useForm } from 'laravel-precognition-vue';

const form = useForm('post', route('test'), {
    test: true,
});

</script>

<template>
    <button
        @click="form.submit()"
    >
        Proceed to payment
    </button>
</template>

web.php

Route::get('/', HomeController::class)->name('home');
Route::post('/test', function () {
    return to_route('home');
})->name('test')->middleware([HandlePrecognitiveRequests::class]);

HomeController.php

<?php

namespace App\Http\Controllers\Pages;

use App\Http\Controllers\Controller;
use Inertia\Inertia;
use Inertia\Response;

/**
 * Class HomeController
 */
class HomeController extends Controller
{
    public function __invoke(): Response
    {
        return Inertia::render('Homepage');
    }
}

processing value always returns false

Laravel Precognition Plugin Version

0.2.2

Laravel Version

10.10

Plugin

React

Description

After implementing precognition on freshly installed laravel + breeze react from default register.jsx file the form.processing value always returns false when the form was submitted and changed the chrome network settings to Slow 3g throttling.

Steps To Reproduce

import { useEffect } from 'react';
import GuestLayout from '@/Layouts/GuestLayout';
import InputError from '@/Components/InputError';
import InputLabel from '@/Components/InputLabel';
import PrimaryButton from '@/Components/PrimaryButton';
import TextInput from '@/Components/TextInput';
import { Head, Link } from '@inertiajs/react';
import {useForm} from 'laravel-precognition-react-inertia'

export default function Register() {
const form = useForm('post', route('register'),{
name: '',
email: '',
password: '',
password_confirmation: '',
});

useEffect(() => {
    return () => {
        form.reset('password', 'password_confirmation');
    };
}, []);

const submit = (e) => {
    e.preventDefault();

    form.submit();
};

return (
    <GuestLayout>
        <Head title="Register" />

        <form onSubmit={submit}>
            <div>
                <InputLabel htmlFor="name" value="Name" />

                <TextInput
                    id="name"
                    name="name"
                    value={form.data.name}
                    className="mt-1 block w-full"
                    autoComplete="name"
                    isFocused={true}
                    onChange={(e) => form.setData('name', e.target.value)}
                    required
                />

                <InputError message={form.errors.name} className="mt-2" />
            </div>

            <div className="mt-4">
                <InputLabel htmlFor="email" value="Email" />

                <TextInput
                    id="email"
                    type="email"
                    name="email"
                    value={form.data.email}
                    className="mt-1 block w-full"
                    autoComplete="username"
                    onChange={(e) => form.setData('email', e.target.value)}
                    required
                />

                <InputError message={form.errors.email} className="mt-2" />
            </div>

            <div className="mt-4">
                <InputLabel htmlFor="password" value="Password" />

                <TextInput
                    id="password"
                    type="password"
                    name="password"
                    value={form.data.password}
                    className="mt-1 block w-full"
                    autoComplete="new-password"
                    onChange={(e) => form.setData('password', e.target.value)}
                    required
                />

                <InputError message={form.errors.password} className="mt-2" />
            </div>

            <div className="mt-4">
                <InputLabel htmlFor="password_confirmation" value="Confirm Password" />

                <TextInput
                    id="password_confirmation"
                    type="password"
                    name="password_confirmation"
                    value={form.data.password_confirmation}
                    className="mt-1 block w-full"
                    autoComplete="new-password"
                    onChange={(e) => form.setData('password_confirmation', e.target.value)}
                    required
                />

                <InputError message={form.errors.password_confirmation} className="mt-2" />
            </div>

            <div className="flex items-center justify-end mt-4">
                <Link
                    href={route('login')}
                    className="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
                >
                    Already registered?
                </Link>
                <PrimaryButton className="ml-4" disabled={form.processing}>
                    Register
                </PrimaryButton>
            </div>
                <p>{`${form.processing}`}</p>
        </form>
    </GuestLayout>
);

}

Allow for forced validation of fields

Hello,

I'm using the laravel-precognition-react frontend library, and on my form I want to allow the user to autocomplete fields. When using Chrome, it will allow for multiple fields to be auto completed at once.
My case is in my multi-step Registration form : in the first step it will fill first name, last name, email and phone.

I've spend the past 2 hours trying to build something that would allow for the autocompleted fields to be validated before moving on to the next step, nothing seems to work properly and feel robust enough to deploy it to users.

Would it be possible to pass a boolean 2nd parameter to the validate function, or expose a separate "forceValidation" method ?

Validate more than one field

I'm using precognition form in a wizard. Every step has some properties of that form.
I'd like, when press next, to validate only fields in the current step.

Is there a way to do it?

Get a method for updating the URL in the form object

For the laravel-precognition-react:

In Next.js, some values do not exist on the page first execution, like access to the localStorage, the window object, or the router query through the useRouter hook.

That means that setting a url for POST/PUT methods like users/[id], where id is set by the url, is imposible, since it only exists after the first render and can be reached only by an useEffect hook

It would be nice to have a method to update the url in the useEffect, like form.setUrl(url:string)

laravel-precognition-vue-inertia `form.clearError('key')` clears all errors

Laravel Version

10.12

PHP Version

8.2

Database Driver & Version

No response

Description

This is really an issue with the precognition package, but there is no repo to submit it ๐Ÿ˜•.

I added laravel-precognition-vue-inertia to my project, when manually calling form.clearErrors('my-field') all errrors are being cleared - unlike inertia's nativeclearErrors function where only my-field errors are being cleared

Steps To Reproduce

Manually call form.clearErrors('my-field') on a form field where there are other field errors already set on the form.

allow useForm method and url to be "reactive"

Hi. I have a vue component (Modal dialog) that can post or patch a record

props: {
  item: Object
}

const form = useForm(method, url, {...})

route and method should change if item is going to be created or updated (for example just check if ID is null)

with inertiajs form I simply set method and route while submitting... but precognition is not reactive...

Is there a workaround? Am I missing something?

Allow for uncontrolled form inputs in React's useForm

The Precognintion documentation page recommends using controlled inputs with useForm.

import { useForm } from 'laravel-precognition-react';
 
export default function Form() {
    const form = useForm('post', '/users', {
        name: '',
        email: '',
    });
 
    const submit = (e) => {
        e.preventDefault();
 
        form.submit();
    };
 
    return (
        <form onSubmit={submit}>
            <label for="name">Name</label>
            <input
                id="name"
                value={form.data.name}
                onChange={(e) => form.setData('name', e.target.value)}
                onBlur={() => form.validate('name')}
            />
            {form.invalid('name') && <div>{form.errors.name}</div>}
 
            <label for="email">Email</label>
            <input
                id="email"
                value={form.data.email}
                onChange={(e) => form.setData('email', e.target.value)}
                onBlur={() => form.validate('email')}
            />
            {form.invalid('email') && <div>{form.errors.email}</div>}
 
            <button>Create User</button>
        </form>
    );
};

useForm state is manage with React's useState hook, so every character typed in a form field causes a re-render. This is fine for smaller forms. However, I have a large grid like forms with hundred's of form inputs. There is substantial lag when typing in a form field which make the form unusable. This is a result of React constantly re-rendering on every key stroke with "controlled inputs". When testing with Vue and Svelte I didn't have this problem because they do state management and re-rending differently.

Kent C Dodds recommends using "uncontrolled inputs" to speed up React form performance (https://epicreact.dev/improve-the-performance-of-your-react-forms/). Basically you hook into the HTML form's native submit event and grab the field values from it instead of having an onChange handler for each form field.

However, this approach is a little difficult to use with useForm currently. If I initialize useForm with no data, then have a submit event handler to set useForm's data from the HTML form submit event, I can't immediately submit the form with precognition. This is because React batches state updates and useForm's data won't be available till next re-render.

import { useForm } from 'laravel-precognition-react';
 
export default function Form() {
    const form = useForm('post', '/users', {});
 
    const submit = (e) => {
        e.preventDefault();
        const formData = new FormData(e.currentTarget);
        const fieldValues = Object.fromEntries(formData.entries());
        form.setData(fieldValues);
        form.submit(); // form.data is not available till next render so won't submit
    };
 
    return (
        <form onSubmit={submit}>
            <label for="name">Name</label>
            <input
                id="name"
                name="name"
            />
 
            <label for="email">Email</label>
            <input
                id="email" 
                name="email"
            />
 
            <button type="submit">Create User</button>
        </form>
    );
};

Is there a way we can enhance useForm to allow use of either "controlled inputs" or "uncontrolled inputs"? I believe this is also a problem in Inertia's userForm.

Possibility to override errors array

hello, is it possible to override the onValidationError method particularly the setErrors(merge(omit({ ...errors }, validate), response.data.errors)); line, i am using laravel resources, and i am formatting the response to a different json format.

i tried to override the response on vue side using this code, it seems to work, but submitting the data doesn't have precognition header, and overriding all response would cause an issue.

Hoping for something like a getErrorKey method or something that set which errors key to use.

client.axios().interceptors.response.use(
  (response) => {
    return Promise.resolve(response);
  },
  (error) => {
    if (error.response.headers?.precognition === "true") {
      error.response.data = {
        message: error.response.data.meta.message,
        errors: error.response.data.meta.error_details,
      };
      return Promise.reject(error);
    }
    return Promise.reject(error);
  }
);

Fields appear as valid before they are set to invalid

Laravel Precognition Plugin Version

0.3.2

Laravel Version

10.10

Plugin

React

Description

When displaying both "valid" and "invalid" status on a field (for example with an icon), and sending a precognitive request with an invalid value, the field will appear as valid before appearing as invalid

Steps To Reproduce

Minimal code can be found on the following public repository : https://github.com/3rgo/demo-laravel-precognitive

Just input an invalid email, either with incorrect format or with an existing value in the database (seeders present and values are displayed on the right side of the page) then switch fields to trigger the validation.

If the field is an array, also validate the items within the array

Thanks for the great package. We are trying to add this to an existing project, and we are coming up a bit short when it comes to validated arrays of data (we are using Vue).

For example:

<script setup>
import { useForm } from 'laravel-precognition-vue';
 
const form = useForm('post', '/contact-groups', {
    name: '',
    emails: [],
});
 
const submit = () => form.submit();
</script>
 
<template>
    <form @submit.prevent="submit">
        <label for="name">Name</label>
        <input
            id="name"
            v-model="form.name"
            @change="form.validate('name')"
        />
        <div v-if="form.invalid('name')">
            {{ form.errors.name }}
        </div>
 
        <label for="emails">Contact Emails</label>
        <ArrayInput
            id="emails"
            v-model="form.emails"
            @change="form.validate('emails')"
        />
        <div v-if="form.invalid('emails')">
            {{ form.errors.emails }}
        </div>
 
        <button :disabled="form.processing">
            Create Contact Group
        </button>
    </form>
</template>

Then in the back end:

protected function rules()
    {
        return [
            'name' => [
                'required',
                'min:3'
            ],
            'emails' => [
               'nullable',
               'array'
            ],
            'emails.*' => [
               'nullable',
               'email'
               'max:255',
            ],
        ];
    }

Given the following form data:

{
  "name": "example",
  "emails": [
    "rttrhrht"
  ]
}

Precognition correctly validates the "emails" array, but it does not check that the items within the array are all emails and therefore shows the form as being completely valid. This is because of the Precognition-Validate-Only header with the value: name,emails. Would it be possible to detect if form.emails is an array, and if so, change the header to name,emails,emails.*?

If this change were to be made, we would also need to have some way of checking which items within the array were invalid. Laravel defaults to errors like this:

{
  "message": "Please ensure you only have valid email addresses",
  "errors": {
    "emails.0": [
      "Please ensure you only have valid email addresses"
    ]
  }
}

We could either simply "reduce" these so that the whole "emails" field shows up as invalid, or we could allow the developer to try to find which keys are invalid with something like form.invalidKeys('emails')

onValidate Callback or async validate

Because a validate does a roundtrip to the server, it would be nice to know when that roundtrip is finished.

For example, we have a multi-step form. The fields in each step need to be valid before being able to proceed to the next step.

I would think adding a couple options to the .validate(), similar to the .submit(), would be a great addition, something like:

form.validate(id, { onValidated: function(isValid: boolean) {} })

Add TypeScript Return Types for useForm

Currently the Inertia useForm for React and Vue has a return type of any, it would be awesome to have it typed.

EDIT: Actually when testing on my fork, we can probably get rid of the implicit any return and let typescript infer the type correctly, but it's giving me an weird error on the vue-inertia package. So probably better to type it!

onValidate callback or async validate (reopen)

This was opened from #56 which I think was inadvertently closed, as it didn't have a resolution. The linked issues have similar questions which I haven't found an answer to yet.

Following is the text of the original issue. I'd be happy to contribute a PR for this, but would like to know if the proposed solution below is a good one or if there is a plan to handle this.

Because a validate does a roundtrip to the server, it would be nice to know when that roundtrip is finished.

For example, we have a multi-step form. The fields in each step need to be valid before being able to proceed to the next step.

I would think adding a couple options to the .validate(), similar to the .submit(), would be a great addition, something like:

form.validate(id, { onValidated: function(isValid: boolean) {} })

Thank you

Method for setting CSRF token on client

Laravel Precognition Plugin Version

0.5.2

Laravel Version

10.35.0

Plugin

Alpine

Description

We have a setup where the CSRF token or cookie may not be available. (We're serving statically cached html).

We need a way to set the X-CSRF-Token header somehow.

I see that there's a way to set the url argument using a function. I think if we could set the config argument with a function, that'll probably work too.

We can grab the token via an ajax request to a route that just returns it.

Route::get('token', fn () => csrf_token());
const getConfig = function () {
  return { headers: { 'X-CSRF-TOKEN': getTokenViaAjax() } };
}

// ...

$form('post', '/the-url', {}, getConfig);

Or maybe a way of modifying the client after the fact.

document.addEventListener('got-csrf-token', () => {
  $form.setHeaders(...);
});

Or maybe there's already a way to do this. Thanks!

Steps To Reproduce

  • Create a route outside of your web routes, so that there is no session.
  • Output {{ csrf_token() }} to the page, see that its blank.
  • Create a form with precognition. The requests will give 419 responses.

laravel-precognition-vue-inertia didnt sent all data

Laravel Precognition Plugin Version

0.4.1

Laravel Version

10.18.0

Plugin

Vue w/ Inertia

Description

I am using laravel precognition to upload a photo and other data. I am using PUT method since I want to update it.

I tried to submit without the image, and i got the response just nice,
When I tried to submit with files, i got errors on all the other fields.

here is my code

const form = useForm(
  props.design ? 'put': "post",
  props.design ? route('designs.update', props.design.uuid):route("projects.designs.store", props.project.uuid),
  {
    images: [],
    type: props.design ? props.design.type:null,
    shortcode: props.design ? props.design.shortcode:null,
    price: props.design ? props.design.price:null,
  },
);

validation

 public function rules()
    {
        return [
            'images.*' => 'required|file|mimes:jpg,png',
            'type' => 'required|string',
            'shortcode' => 'required|alpha_dash|string|max:20|unique:designs,shortcode,' . $this->route('design')->id,
            'price' => 'required|numeric|min:1',
        ];
    }

Steps To Reproduce

Create a form with file input and some other fields, and use PUT method.

Cannot find module /node_modules/laravel-precognition/dist/client'

Laravel Precognition Plugin Version

0.3.2

Laravel Version

10.4.1

Plugin

React

Description

  • ready started server on 0.0.0.0:3000, url: http://localhost:3000
  • event compiled client and server successfully in 556 ms (18 modules)
  • wait compiling...
  • event compiled client and server successfully in 121 ms (18 modules)
  • wait compiling /_error (client and server)...
  • wait compiling /login (client and server)...
  • event compiled client and server successfully in 3.6s (1272 modules)
  • warn Fast Refresh had to perform a full reload. Read more: https://nextjs.org/docs/messages/fast-refresh-reload
  • error Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/thuraaung/Works/solinx/next-testing/node_modules/laravel-precognition/dist/client' imported from /Users/thuraaung/Works/solinx/next-testing/node_modules/laravel-precognition/dist/index.js
    at new NodeError (node:internal/errors:399:5)
    at finalizeResolution (node:internal/modules/esm/resolve:231:11)
    at moduleResolve (node:internal/modules/esm/resolve:850:10)
    at ESMLoader.defaultResolve (node:internal/modules/esm/resolve:1058:11)
    at ESMLoader.resolve (node:internal/modules/esm/loader:323:32)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:172:38)
    at ModuleWrap. (node:internal/modules/esm/module_job:76:40)
    at link (node:internal/modules/esm/module_job:75:36) {
    digest: undefined
    }
Screenshot 2023-07-15 at 12 25 57 PM

Steps To Reproduce

Here i just done

form reset() w/o params doens't reset old values

Laravel Precognition Plugin Version

0.5.2

Laravel Version

10.29

Plugin

Vue w/ Inertia

Description

when call form.reset() without names parameters validator doesn't reset old values.

core/validator.js

reset(...names) {
    if (names.length === 0) {
        setTouched([]) // <--- oldData is not reset
    } else {
        const newTouched = [...touched]

        names.forEach(name => {
            if (newTouched.includes(name)) {
                newTouched.splice(newTouched.indexOf(name), 1)
            }

            set(oldData, name, get(initialData, name))
        })

        setTouched(newTouched)
    }

    return form

next validation request doesn't start.

works if I reset with parameters

Steps To Reproduce

form.defaults({
  first_name: '',
  last_name: ''
}).reset()

form.touch('first_name', 'last_name')
form.validate() // <-- make request

form.reset()
form.touch('first_name', 'last_name')
form.validate() // <-- no request

form.reset('first_name', 'last_name')
form.touch('first_name', 'last_name')
form.validate() // <-- make request

Arrays being sent as empty when using "laravel-precognition-react-inertia"

Laravel Precognition Plugin Version

0.2.2

Laravel Version

10.13.0

Plugin

React

Description

For some reason, when sending a "precognition" request, the arrays are empty - in this case I have this type definition:
demo?: {items: string[]}; and the data is set to demo: {items: ["foo", "bar"]}, and when the form is submitted to the backend to be created, the data is correct - but when doing a precognition validation, the arrays are empty.

Please see the screenshot. The console.log statement is triggered just before the calling form.validation(...) method.

Initially I thought it was because I was calling the validation on a different field, but I can see that rest of the form data is sent along, but all arrays are just truncated.

Screenshot 2023-06-05 at 10 57 25

Steps To Reproduce

const initialValues = {
        email: "[email protected]",
        demo: ["foo", "bar"],
};

const actionRoute = "/store";
const form = useForm('post', actionRoute, initialValues);

function submit(e: FormEvent) {
      e.preventDefault();
      console.log(form.data);
      form.post(actionRoute);
}

return (
<form method='POST' action={actionRoute} onSubmit={submit}>
<input
      type='email'
      value={form.data.email}
      onChange={e => form.setData('email', e.target.value)}
      onBlur={() => {console.log(form.data); return form.validate('email')}}
  />

<button type='submit'>YOLO</button>
</form>
)

Form reporting incorrectly valid

Laravel Precognition Plugin Version

0.5.2

Laravel Version

10.35.0

Plugin

Vue w/ Inertia

Description

I checked this multiple times just to be sure, and here are the results:

  1. When no validation is done - reporting correctly "invalid()" to be false and "valid()" to be false
Screenshot 2023-12-13 at 14 45 53
  1. When validated with a correct value - reporting correctly "invalid()" to be false and "valid()" to be true
Screenshot 2023-12-13 at 14 45 59
  1. When validating with a not correct value - reporting "invalid()" to be true (correct) and "valid()" to be true (not correct):
Screenshot 2023-12-13 at 14 46 06

Expecting on 3rd example "invalid()" to be true and "valid()" to be false. It seems to me that currently the "valid()" acts as "isdirty" so the current name is misleading.

As a workaround, I use "!form.invalid(field) && form.valid(field)" to show the valid notification.

Steps To Reproduce

<template>
invalid: {{ form.invalid('postalcode') }}<br>
valid: {{ form.valid('postalcode') }}<br>
<label for="postalcode">Postiindeks</label>
<input type="text" name="postalcode" v-model="form.postalcode" @change="form.validate('postalcode')">
</template>

<script setup>
import {useForm} from 'laravel-precognition-vue-inertia';

const form = useForm('post', 'valid-endpoint', {
  postalcode: null,
});
</script>

The validator:

<?php
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class SettingsRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'postalcode' => 'nullable|digits_between:10000,99999',
        ];
    }

async validate()

Is there a way to do this?
In other words... wait for validation response

function async nextStep() {
    await form.touch(["name", "email", "password", "password_validation"]).validate();

    return form.hasError
}

Laravel Precognition returns wrong values for valid and invalid when field is not yet touched

Laravel Precognition Plugin Version

0.3.2

Laravel Version

10.14.1

Plugin

Vue w/ Inertia

Description

When checking for the validity of a untouched field, the methods "valid" and "invalid" both return false. The issue with this behaviour is that nullable fields are wrongly classified as invalid when using the "valid" method and required fields are wrongly classified as valid when using the "invalid" method.

I think a initial request to check for required fields would be helpful, so that the "valid" and "invalid" methods can be used before the user has even interacted with the form.

Steps To Reproduce

You can see the issue in this repository: "https://github.com/Sagmedjo/precognitionIssue". When submitting the form look into the DevTools Console

Cannot use 'data' as a form property

Laravel Precognition Plugin Version

0.5.3

Laravel Version

10.40.0

Plugin

Vue

Description

Because the properties of the form are merged together with form functions here, it's not possible to have a property on the form that has the same name as any of the functions.

Steps To Reproduce

Example setup function of a Vue component, using a 'data' property:

const form = useForm('post', '/api/my-endpoint', {
    'data': {
        'foo': 1,
        'bar': 2,
    },
    'some_other_property': 1,
});

return { form };

When trying to submit the form using form.submit(), you'll get the following error because the 'data' property conflicts with the data function:

TypeError: form.data is not a function. (In 'form.data()', 'form.data' is an instance of ProxyObject)

Laravel Precognition For Inertia Svelte

Can we please get the Inertia Svelte version? Since Inertia could be implemented in React, Vue, and Svelte. I think it makes sense to have the Inertia Svelte version too.

Add support to force-validate specific fields (even if untouched)

Hi there !

I'm trying to implement a multi-step form (in the same page) and I'm using laravel-precognition-vue-inertia
I can't find a practical way to force validation for the fields contained in each step of the form even if they are untouched (in the handler of the "Next step" button for example) without affecting the whole form (fields in other steps) or submitting it .
How to achieve this behaviour?

Remember state on precognition form

Hello!

I am currently rewriting every useForm() instance to the precognition variant (import { useForm } from 'laravel-precognition-vue-inertia';). I want to "remember" the state of the form after submission, so the form is still "in tact" when going back to the form.

I used to do this with: const form = useForm(`CreateQuote:${usePage().props.user.id}`, {, but this does not work anymore. Does someone have a workaround to still accomplish this or is this not a feature (yet)? Thanks!

Bug: 422 (Unprocessable Content)

Laravel Precognition Plugin Version

0.5.2

Laravel Version

10.10

Plugin

Vue w/ Inertia

Description

Every time input changes and blurs it gives this error: POST http://127.0.0.1:8000/login 422 (Unprocessable Content), but the error correctly shows.

Steps To Reproduce

  1. composer create-project laravel/laravel example-app
  2. cd example-app
  3. composer require laravel/breeze --dev
  4. php artisan breeze:install
  5. php artisan migrate
  6. npm install laravel-precognition-vue-inertia
  7. Add middleware:
Route::post('login', [AuthenticatedSessionController::class, 'store'])->middleware([HandlePrecognitiveRequests::class]);
  1. Change the login page to use useForm from "laravel-precognition-vue-inertia":
const form = useForm("post", route("login"), {
    email: "",
    password: "",
    remember: false,
});

const submit = () => {
    form.submit({
        onFinish: () => {
            form.reset("password");
        },
    });
};
  1. Add @change="() => form.validate('email')" to inputs:
<TextInput
    id="email"
    type="email"
    class="mt-1 block w-full"
    v-model="form.email"
    @change="form.validate('email')"
    required
    autofocus
    autocomplete="username"
/>

<InputError class="mt-2" :message="form.errors.email" />

<TextInput
    id="password"
    type="password"
    class="mt-1 block w-full"
    v-model="form.password"
    @change="form.validate('password')"
    required
    autocomplete="current-password"
/>

<InputError class="mt-2" :message="form.errors.password" />
  1. mysqld --console
  2. php artisan serve
  3. npm run dev
  4. Go to the login page
  5. Add any value to email or password and blur the input
  6. Console Error!

form.submit with validate array does not work

Laravel Precognition Plugin Version

0.3.1

Laravel Version

10.0

Plugin

Vue

Description

I would like to add which fields on the form should be validated on submit. I would expect that populating the optional validate property with an array of paths would do this.
e.g.

@change="form.validate('assets.0.address.zipcode' )"
works

but this doesn't:

const submit = () => {
    form.submit({
        validate: ['assets.0.address.zipcode', 'assets.0.address.number'],
    });
};

Steps To Reproduce

add the code as mentioned in the description to your form
change the name(s) in the array of thevalidate property
See that it validates the whole form, instead of just the given names ('assets.0.address.zipcode', 'assets.0.address.number')

Error in Precognition React using Sanctum

Laravel Precognition Plugin Version

0.5.2

Laravel Version

10.31.0

Plugin

React

Description

I installed Laravel Breeze API and create the login component in React.

api:

import axios from "axios";
import { config } from "@/config/config";

function client(baseURL: string | undefined) {
  const client = axios.create({ baseURL, withCredentials: true });

  client.defaults.headers.common["Accept"] = "application/json";
  client.defaults.headers.common["Content-Type"] = "application/json";

  return client;
}

const api = client(config.NEXT_PUBLIC_API_URL);

export default api;

sanctumRepository:

import api from '@/services/api';

export const csrf = () => api.get('/sanctum/csrf-cookie');

login:

  client.use(api);

  const form = useForm("post", "/login", {
    email: "",
    password: "",
    remember: false,
  });

  const submit = async (e: any) => {
    e.preventDefault();

    await csrf();

    form
      .submit()
      .then((data) => {
        console.log(data);
      })
      .catch((error) => {
        console.log(error);
      });
  };

Error:

{
    "message": "CSRF token mismatch.",
    "exception": "Symfony\\Component\\HttpKernel\\Exception\\HttpException",
    "file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php"
}

Steps To Reproduce

Install Laravel Breeze API and try to use Precognition React.

Support for Nuxt 3 or add axios configuration

Hey,

first of all thank you for this library. For inertia or vue based projects this works just fine.

For Nuxt 3 projects precognition is currently not working. I already tried a few approaches but there are some general problems integrating it:

  1. Nuxt 3 is not using axios. Instead it relies on the ofetch library which uses the standard Fetch API internally. I already managed authentication and csrf token with fetch.
  2. Precognition uses axios internally. This is fine for inertia or vue projects. For Nuxt 3 this is not needed, because useFetch() should be used.
  3. If I use the precognition-vue in a clientonly component the requests are sent without problems, but laravel returns 419 status, because there is no CSRF cookie set.

Ideas:

  • Support fetch api/Nuxt's useFetch method
  • or: make http library configurable
  • or: make axios configurable through library to use an already existing CSRF Cookie as Header

If I can help to Support Nuxt 3 I am glad to. If I understand it correctly this shouldn't be a big problem, because the library just sends requests to the same endpoint the form would be submit to, including Special precognition headers and the data value. Handling request sending itself is done by using vue/nuxt onchange events.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.