Learn Nuxt with a Collection of 100+ Tips!

laravel-precognition
laravel-precognition

Nuxt module to work with Laravel Precognition and $fetch

Nuxt (Laravel) Precognition - DEPRECATED

This package has been deprecated. I recommend using nuxt-precognition for future projects.

Why switch to nuxt-precognition?

  • Nitro support.
  • Backend Agnostic.
  • Simplify and more robust API.
  • Frontend validation.

🚀 Switch to nuxt-precognition

How to migrate.

Api of the new module is very similar but useForm now support generic promises, therefor input arguments are different (specify method and URL are no longer required).

Benefits on migrating

Even if you work with Laravel only backend, the new API is better and more flexible. There is no need to use different parameters (bodyAs) for sending FormData or URLSearchParams. You won't need a Laravel backend only for contact Form!!

Following the idea Nuxt is becoming a FULL stack framework, why not adding this awesome funciontality of precognitive validation? For any comments or suggestion don't hesitate of contact me!!

Nuxt (Laravel) Precognition

npm versionnpm downloadsLicenseNuxt

Module for Nuxt3, supporting Laravel Precognition using native $fetch.

This is opinionated module. Although most functionalities have been replicated to work with $fetch API, there are minor differences

Features

  • base functionalities of official modules
  • Better typescript support for objects with nested keys
  • Added queryAs and bodyAs for sending data as FormData or URLSearchParams...

Quick Setup

  1. Add nuxt-laravel-precognition dependency to your project
npx nuxi@latest module add laravel-precognition
  1. Add nuxt-laravel-precognition to the modules section of nuxt.config.ts
export default defineNuxtConfig({
  modules: [
    'nuxt-laravel-precognition'
  ]
})
  1. Create one plugin where you initialize the $fetch client, and then use it as precognition client:
import { defineNuxtPlugin, useCookie, useNuxtApp } from '#app'

export default defineNuxtPlugin(() => {
  function getCsrfToken() {
    // grab sanctum headers
    return useCookie('XSRF-TOKEN', { default: () => '' }).value
  }

  function mergeHeaders(options: { headers?: HeadersInit }, newHeaders: HeadersInit) {
    const headersToBeMerged = new Headers(newHeaders) // cast newHeaders to Headers instance

    // check if request has headers to be merged with newHeaders
    if (!options.headers) { 
      options.headers = headersToBeMerged
      return
    }

    options.headers = new Headers(options.headers) // cast requestHeaders to Headers instance

    // merge the newHeaders with requestHeaders
    Array.from([...headersToBeMerged.entries()]).forEach(([key, value]) => {
      (options.headers as Headers).set(key, value)
    })
  }

  const api = $fetch.create({
    baseURL: 'http://localhost',
    headers: {
      Accept: 'application/json',
    },
    credentials: 'include',
    onRequest: ({ options }) => {
      const csrfToken = getCsrfToken() // read sanctum csrf token

      if (!csrfToken)
        return

      mergeHeaders(options,  ['X-XSRF-TOKEN', csrfToken]) // attach the csrf token as X-XSRF-TOKEN header
    },
  })

  const { $precognition } = useNuxtApp()

  $precognition.client.use(api)

  function fetchCsrfToken() {
    return api('/sanctum/csrf-cookie')
  }

  return {
    provide: {
      api,
      fetchCsrfToken,
    },
  }
})
  1. Remember to expose laravel Precognition Headers in your config/cors.php laravel file:
return [

    /*
    |--------------------------------------------------------------------------
    | Cross-Origin Resource Sharing (CORS) Configuration
    |--------------------------------------------------------------------------
    |
    */

    'paths' => ['*'],

    'allowed_methods' => ['*'],

    'allowed_origins' => ['*'],

    'allowed_origins_patterns' => [env('FRONTEND_URL', 'http://localhost:3000')],

    'allowed_headers' => ['*'],

    'exposed_headers' => ['Precognition', 'Precognition-Success'],

    'max_age' => 0,

    'supports_credentials' => true,

];
  1. You can use the useForm composable that is autoimported by this module.