tighten / ziggy

Use your Laravel routes in JavaScript.
MIT License
3.83k stars 247 forks source link

Vue: Cannot convert undefined or null to object #739

Closed sweptsquash closed 4 months ago

sweptsquash commented 4 months ago

Ziggy version

2.1.0

Laravel version

11.1.1

Description

Hi,

When I use the route helper function for example fetching the current page with route().current() I'm given the error Cannot convert undefined or null to object, this also occurs with getting a route with route('news.index').

In my app.js I'm defining the plugin and passing the exported config like so. However if I add globalThis.Ziggy = Ziggy; to the app.js the error goes away. Not sure if this is intended given I'm passing the config to the plugin.

import '../css/app.css'
import Layout from '@/layouts/default.vue'
import { createInertiaApp } from '@inertiajs/vue3'
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers'
import { ZiggyVue } from 'ziggy-js'
import { Ziggy } from '@/routes/routes.js'
import { createApp, h } from 'vue'

createInertiaApp({
    progress: {
        color: '#4B5563',
    },
    resolve: (name) =>
        resolvePageComponent(`./pages/${name}.vue`, import.meta.glob('./pages/**/*.vue')).then(
            (module) => {
                const page = module.default

                page.layout = page.layout || Layout

                return page
            },
        ),
    setup({ el, App, props, plugin }) {
        createApp({ render: () => h(App, props) })
            .use(plugin)
            .use(ZiggyVue, Ziggy)
            .mount(el)
    },
})

In my NavBar.vue script I have the following onBeforeMount to set the current active link for styling:

const navigationItems = ref([
    { name: 'News', href: '/news', route: 'news.*', current: false },
    { name: 'Reviews', href: '/reviews', route: 'reviews', current: false },
    { name: 'Guides', href: '/guides', route: 'guides', current: false },
    { name: 'Schedule', href: '/schedule', route: 'schedule', current: false },
    { name: 'About', href: '/about', route: 'about', current: false },
])

onBeforeMount(() => {
    router.on('navigate', () => {
        const currentActive = navigationItems.value.findIndex((item) => item.current === true)
        const newActive = navigationItems.value.findIndex((item) => {
            if (item.route === null) {
                return false
            }

            return route().current(item.route)
        })

        if (newActive === -1 && currentActive !== -1) {
            navigationItems.value[currentActive].current = false
        }

        if (newActive > -1 && currentActive !== newActive) {
            if (currentActive !== -1) {
                navigationItems.value[currentActive].current = false
            }

            navigationItems.value[newActive].current = true
        }
    })
})

Ziggy call and context

Uncaught TypeError: Cannot convert undefined or null to object
    at Function.entries (<anonymous>)
    at n.u (ziggy-js.js?v=3272b7cd:743:29)
    at n.current (ziggy-js.js?v=3272b7cd:751:65)
    at NavBar.vue:21:28
    at Proxy.findIndex (<anonymous>)
    at NavBar.vue:16:49
    at HTMLDocument.n (@inertiajs_vue3.js?v=3272b7cd:4157:16)
    at f (@inertiajs_vue3.js?v=3272b7cd:3878:19)
    at S (@inertiajs_vue3.js?v=3272b7cd:3885:16)
    at @inertiajs_vue3.js?v=3272b7cd:3959:96

Ziggy configuration

{
    url: 'http://localhost:8000',
    port: 8000,
    defaults: {},
    routes: {
        'filament.exports.download': {
            uri: 'filament/exports/{export}/download',
            methods: ['GET', 'HEAD'],
            parameters: ['export'],
            bindings: { export: 'id' },
        },
        'filament.imports.failed-rows.download': {
            uri: 'filament/imports/{import}/failed-rows/download',
            methods: ['GET', 'HEAD'],
            parameters: ['import'],
            bindings: { import: 'id' },
        },
        'filament.admin.auth.login': {
            uri: 'admin/login',
            methods: ['GET', 'HEAD'],
            domain: 'admin.senshudo.tv',
        },
        'filament.admin.auth.logout': {
            uri: 'admin/logout',
            methods: ['POST'],
            domain: 'admin.senshudo.tv',
        },
        'filament.admin.pages.dashboard': {
            uri: 'admin',
            methods: ['GET', 'HEAD'],
            domain: 'admin.senshudo.tv',
        },
        'sanctum.csrf-cookie': { uri: 'sanctum/csrf-cookie', methods: ['GET', 'HEAD'] },
        'livewire.update': { uri: 'livewire/update', methods: ['POST'] },
        'livewire.upload-file': { uri: 'livewire/upload-file', methods: ['POST'] },
        'livewire.preview-file': {
            uri: 'livewire/preview-file/{filename}',
            methods: ['GET', 'HEAD'],
            parameters: ['filename'],
        },
        'ignition.healthCheck': { uri: '_ignition/health-check', methods: ['GET', 'HEAD'] },
        'ignition.executeSolution': { uri: '_ignition/execute-solution', methods: ['POST'] },
        'ignition.updateConfig': { uri: '_ignition/update-config', methods: ['POST'] },
        'articles.index': { uri: 'api/articles', methods: ['GET', 'HEAD'] },
        'articles.homepage': { uri: 'api/articles/homepage', methods: ['GET', 'HEAD'] },
        'articles.featured': { uri: 'api/articles/featured', methods: ['GET', 'HEAD'] },
        'articles.show': {
            uri: 'api/articles/{article}',
            methods: ['GET', 'HEAD'],
            parameters: ['article'],
            bindings: { article: 'slug' },
        },
        'categories.index': { uri: 'api/categories', methods: ['GET', 'HEAD'] },
        'categories.show': {
            uri: 'api/categories/{category}',
            methods: ['GET', 'HEAD'],
            parameters: ['category'],
            bindings: { category: 'id' },
        },
        search: { uri: 'api/search', methods: ['GET', 'HEAD'] },
        home: { uri: '/', methods: ['GET', 'HEAD'] },
        'news.index': { uri: 'news', methods: ['GET', 'HEAD'] },
        'news.show': {
            uri: 'news/{article}',
            methods: ['GET', 'HEAD'],
            parameters: ['article'],
            bindings: { article: 'slug' },
        },
    },
}

Route definition

Route::get('/', HomepageController::class)->name('home');

Route::prefix('news')->name('news.')->group(function () {
    Route::get('/', [NewsController::class, 'index'])->name('index');
    Route::get('/{article}', [NewsController::class, 'show'])->name('show');
});