chirag-techrayslabs's avatar

Need help with Laravel precognition using alpine

I have followed the official doc of Laravel Precognition and it is working fine if I define x-data as shown there.

But I want to make small change so the code looks better, Below is my code.

<x-app-layout title="Roles" is-sidebar-open="true" is-header-blur="true">
    <main class="main-content w-full px-[var(--margin-x)] pb-8">
        <div class="flex items-center justify-between space-x-4 py-5 lg:py-6">
            <h2 class="text-xl font-medium text-slate-800 dark:text-navy-50 lg:text-2xl">
                Add New Role
            </h2>
        </div>
        <div class="card p-4 sm:p-5 space-y-4">
            <form x-data="validateForm" method="POST" action="{{ route('manage.roles.store') }}">
                @csrf
                <div class="grid grid-cols-1 gap-4 sm:grid-cols-3">
                    <x-forms.inputs.text label="Name" name="name" placeholder="Name" />
                    <h2
                        class="font-medium tracking-wide text-slate-700 line-clamp-1 dark:text-navy-100 lg:text-base sm:col-span-3 col-span-1">
                        Permissions
                    </h2>
                    <div class="sm:col-span-3 col-span-1">
                        <x-forms.inputs.multiple-switches name="permissions" :options="$permissionsOptions" valueField="name"
                            labelField="name" :selected="old('permissions', [])" />
                    </div>
                </div>
                <div class="flex justify-end space-x-2  mt-4">
                    <x-forms.inputs.submit label="Save" icon="fa fa-save" />
                </div>
            </form>
        </div>
    </main>
    @push('scripts')
        <script>
            document.addEventListener('alpine:init', () => {
                Alpine.data('validateForm', () => ({
                    form: $form('post', '/validate/roles/create', {
                        name: '',
                    }),
                }));
            });
        </script>
    @endpush
</x-app-layout>

I am getting Uncaught ReferenceError: $form is not defined here when trying to use like this. In the normal case as mentioned in the official doc it is working. I am on alpinejs version 3.

0 likes
6 replies
chirag-techrayslabs's avatar
Level 1

For anyone looking for the solution in future.

Custom "magics" are not available when the data-object is created, but can be used in the init() function. This should work:

Alpine.data('validateForm', () => ({

   form: null,

   init: function () {

       this.form = this.$form('post', '/validate/roles/create', {
           name: ''
       })
   }
}));
Ajrhgouns's avatar

@chirag-techrayslabs I am still not able to get validation errors at my frontend

DO I need to setup axios or anything?

I am using laravel blade files only

I have product resource controller below is my code

<label for="price">price</label>
<input id="price" name="price" x-model="form.price" @change="form.validate('price')" />
<template x-if="form.invalid('price')">
    <div x-text="form.errors.price"></div>
</template>

<button :disabled="form.processing">
    Create Product
</button>
<script>
    document.addEventListener('alpine:init', () => {
        Alpine.data('validateForm', () => ({
            form: null,
            init: function() {
                this.form = this.$form('post', '/products', {
                    name: '',
                    price: 0
                })
            }
        }));
    });
</script>

@endpush

chirag-techrayslabs's avatar

@Ajrhgouns Have you setup route to use the HandlePrecognitiveRequests middleware? if yes please check in network tab if requests are being sent or not.

Ajrhgouns's avatar

Hello Chirag

Thank you for your response

Here is my web.php file code

Route::resource("products", ProductController::class)->middleware([HandlePrecognitiveRequests::class]);

Requests are done on the backend and backend validations are also applied

chirag-techrayslabs's avatar

@Ajrhgouns in that case try this

<script>
    document.addEventListener('alpine:init', () => {
        Alpine.data('validateForm', () => ({
            form: null,
            init: function() {
                this.form = this.$form('post', '/products', {
                    name: '',
                    price: 0
                }).setErrors({{ Js::from($errors->messages()) }});
            }
        }));
    });
</script>

Ajrhgouns's avatar

Now I am able to make validation request to the backend whenever I make change to inputs

But I got these errors

  1. Detected multiple instances of Alpine running
  2. getting 422 status code for

form method="POST" action="{{ route('products.store') }}" x-data="{ form: $form('post', '/products', { name: '', price: 0 }) }">

here is my latest code

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
                <form method="POST" action="{{ route('products.store') }}" x-data="{
                    form: $form('post', '/products', {
                        name: '',
                        price: 0
                    })
                }">
                    @csrf
                    <label for="name">Name</label>
                    <input id="name" name="name" x-model="form.name" @change="form.validate('name')" />
                    <template x-if="form.invalid('name')">
                        <div x-text="form.errors.name"></div>
                    </template>

                    <label for="price">price</label>
                    <input id="price" name="price" x-model="form.price" @change="form.validate('price')" />
                    <template x-if="form.invalid('price')">
                        kk
                        <div x-text="form.errors.price"></div>
                    </template>

                    <button type="submit">
                        Create Product
                    </button>
                </form>
            </div>
        </div>
    </div>

</x-app-layout>

<script>
    document.addEventListener('alpine:init', () => {
        Alpine.data('validateForm', () => ({
            form: null,
        }));
    });
</script> ```

Please or to participate in this conversation.