Kevin
Kevin

Reputation: 62

Why are my ziggy routes not working when Javascript is disabled?

I'm using Ziggy routes in my Laravel (Inertia/Vue3) site. I'm using Server Side Rendering. The routes work fine when Javscript is enabled. The routes don't work when Javascript is disabled or when a search engine tries to crawl the site.

You can see an example here: https://kitcollect.com/register.

If you mouse over the "Already registered" link with javascript enabled, you'll see the url "https://kitcollect.com/register/login".

If you click the link with Javascript enabled, you get redirected to "https://kitcollect.com/login" , as you should. If you disable javacript and click the link, it sends you to "https://kitcollect.com/register/login". It treats the link like a relative link.

My component is generating that link using the following:

<Link
                    :href="route('login')"
                    class="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>

The login route it's referencing is the standard Laravel login route: Route::get('login', [AuthenticatedSessionController::class, 'create']) ->name('login');

This is what my HandleInertiaRequests middleware looks like:

<?php

namespace App\Http\Middleware;

use Illuminate\Http\Request;
use Inertia\Middleware;
use Auth;
use Tightenco\Ziggy\Ziggy;
class HandleInertiaRequests extends Middleware
{
    /**
     * The root template that is loaded on the first page visit.
     *
     * @var string
     */
    protected $rootView = 'app';

    /**
     * Determine the current asset version.
     */
    public function version(Request $request): string|null
    {
        return parent::version($request);
    }

    /**
     * Define the props that are shared by default.
     *
     * @return array<string, mixed>
     */
    public function share(Request $request): array
    {
        $ziggy = new Ziggy($group=null, $request->url());

        return [
            ...parent::share($request),
            'auth' => [
                'auth_user' => $request->user(),
                'user'=>\App\Models\User::with('wishlist')->find(Auth::id())
            ],
            'flash'=>[
                'success'=>fn()=>$request->session()->get('success'),
                'error'=>fn()=>$request->session()->get('error')
            ],
            'ziggy'=>$ziggy->toArray()
        ];
    }
}

My app.js

import './bootstrap';
import '../css/app.css';

import { createSSRApp, h } from 'vue';
import { createInertiaApp } from '@inertiajs/vue3';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { ZiggyVue } from '../../vendor/tightenco/ziggy/dist/vue.m';

const appName = import.meta.env.VITE_APP_NAME || 'Laravel';

createInertiaApp({
    title: (title) => `${title} - ${appName}`,
    resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')),
    setup({ el, App, props, plugin }) {
        return createSSRApp({ render: () => h(App, props) })
            .use(plugin)
            .use(ZiggyVue)
            .mount(el);
    },
    progress: {
        color: '#4B5563',
    },
});

I've tried changing the uri of the route from Route::get('login', [AuthenticatedSessionController::class, 'create']) ->name('login'); to Route::get('/login', [AuthenticatedSessionController::class, 'create']) ->name('login');

It doesn't make a difference.

This issue is problematic for me because search engines are following these bad routes.

Does anyone have any suggestions?

Upvotes: 0

Views: 1071

Answers (1)

PHANTOM-X
PHANTOM-X

Reputation: 586

In laravel v11+ change make sure you use use Tighten\Ziggy\Ziggy; instead of use Tightenco\Ziggy\Ziggy; used in older versions

and in your return


        return [
            ...parent::share($request),
            'auth' => [
                'user' => $request->user()
            ],
            'ziggy' => function () use ($request) {
                return array_merge((new Ziggy)->toArray(), [
                    'location' => $request->url(),
                    'query' => $request->query()
                ]);
            },
        ];

which returns an object


{
    "url": "http://your-app-url:8080",
    "port": 8080,
    "defaults": [],
    "routes": {
        "pulse": {
            "uri": "pulse",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
...
 },
    "location": "http://your-app-url:8080/profile",
    "query": {
        "tab": "profile-edit"
    }
}

then you can access it in javascript qhen you visit this url http://your-app-url:8080/profile?tab=profile-edit

If you're using inertiajs you can visit your link with query passed


import { router } from '@inertiajs/react'


  const goToProfileEditTab = () => {
    router.visit(route('profile.edit', [{ tab: 'profile-edit' }]))
  }

...

<button onClick={() => goToProfileEditTab()}>goToProfileEditTab</button>


const tab = props.ziggy.query.tab

console.log(tab)
// profile-edit

Upvotes: 0

Related Questions