Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Persistent layout problems #613

Closed
stuartcusackie opened this issue Jan 25, 2023 · 5 comments
Closed

Persistent layout problems #613

stuartcusackie opened this issue Jan 25, 2023 · 5 comments

Comments

@stuartcusackie
Copy link

stuartcusackie commented Jan 25, 2023

Ziggy version

1.5.0

Laravel version

9.48.0

Description

Following on from this issue, route().current() does not update when using inertia persistent / default layouts. The return value never changes after initial app load.

I'm not sure if this is an Inertia or Ziggy problem. I can open an inertia issue but I'm not sure how to address it.

I have tested this like so:

Ziggy call and context

Simply calling:
{{ route().current() }}
within my page component template

Ziggy configuration

defaults: {}
port: null
routes: 
artists.index: 
{uri: 'our-voices', methods: Array(2)}
home: 
{uri: '/', methods: Array(2)}

Route definition

Route::get('/', [PageController::class, 'index'])->name('home');
Route::get('/our-voices', [ArtistController::class, 'index'])->name('artists.index');
@bakerkretzmar
Copy link
Collaborator

route().current() checks the URL of the window at the time it's called, it's not connected to Inertia or Vue and never 'updates'. If you're saving route().current() into a variable in a parent component that doesn't re-render when the URL changes, then it's only being called once and that value will become stale because it's never generated again. You need to call route().current() every time the URL might have changed, e.g. by listening for Inertia's navigation events.

Feel free to share more code samples or a repo with an example of this and I can suggest some specific solutions!

@bakerkretzmar bakerkretzmar closed this as not planned Won't fix, can't repro, duplicate, stale Jan 27, 2023
@stuartcusackie
Copy link
Author

stuartcusackie commented Jan 27, 2023

Thanks for the reply. After more research it seems that 'Peristent' layouts in Inertia behave differently than I expected. Properties of persistent layouts are non-reactive. That's why my template wasn't updating on route change.

If you still need persistent layouts then I will add my solution below. For the moment I can do without them, but I know they are useful for some things.

ORIGINAL CODE (my 'active' link never updated with persistent layouts):

<template>
    <nav class="flex">
        <NavBarLink
            :href="route('home')"
            :active="route().current('home')"
            >Home</NavBarLink>

        <NavBarLink
            :href="route('artists.index')"
            :active="route().current('artists.index')"
            >Artists</NavBarLink>
    </nav>
</template>

<script setup>
import NavBarLinkfrom '@/Components/NavBarLink.vue';
</script>

SOLUTION FOR PERSISTENT LAYOUTS:

<template>
    <nav class="flex">
        <NavBarLink
            :href="route('home')"
            :active="testRoute.current == 'home'"
            >Home</NavBarLink>

        <NavBarLink
            :href="route('artists.index')"
            :active="testRoute.current == 'artists.index'"
            >Artists</NavBarLink>
    </nav>
</template>

<script setup>
import { reactive } from 'vue';
import { router } from '@inertiajs/vue3'
import NavBarLink from '@/Components/NavBarLink.vue';

const testRoute = reactive({current: route().current()});

router.on('navigate', (event) => {
    testRoute.current = route().current();
})
</script>

@sebsobseb
Copy link

sebsobseb commented Jun 30, 2023

While the solution of @stuartcusackie works, I used a slightly different approach which forces the nav component to refresh on each navigation, meaning you can still use the route.current() method as usual (e.g. route().current('events.*') because it gets re-evaluated on each navigation.

<template>
    <nav :key="currentRoute" class="flex">
        <NavBarLink
            :href="route('home')"
            :active="route.current('home')"
            >Home</NavBarLink>

        <NavBarLink
            :href="route('artists.index')"
            :active="route.current('artists.*')"
            >Artists</NavBarLink>
    </nav>
</template>

<script setup>
import { ref } from 'vue';
import { router } from '@inertiajs/vue3';
import NavBarLink from '@/Components/NavBarLink.vue';

const currentRoute = ref(null);

router.on('navigate', () => {
    currentRoute.value = route().current();
})
</script>

It listens to Inertia's navigate event and updates the local currentRoute value.
Since I added a :key attribute to the component it will be re-rendered each time currentRoute changes.

More info about this 'key changing technique': https://michaelnthiessen.com/key-changing-technique/

@plweil
Copy link

plweil commented Jul 28, 2023

I just ran into this myself. I'm not using a persistent layout; just a child layout component. Since the Ziggy method won't work on its own, wouldn't it be simpler to bypass it and add the current route via the HandleInertiaRequests middleware? Then it's available in any child component.

E.g.,

return array_merge(parent::share($request), [
currentRoute' => fn () => Route::currentRouteName(),
]);

Then in the layout component:

<script setup>
import { Link, usePage } from '@inertiajs/vue3';

const {props} = usePage()
</script>
<template>
<div>{{ props.currentRoute }} </div>
</template>

@mrleblanc101
Copy link

Shouldn't this be reactive in a way ?
What's the point of the Vue plugin then ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants