NuxtLink to dynamic page with Prismic data only works when opened in new tab

Hello!

My Nuxt 3 index page has a component that uses data from prismic to link to a dynamic page like this:

<script setup>
    const { client } = usePrismic()
    const { data: werke } = await useAsyncData('werk', () => client.getAllByType('werk'))
</script>


<template> 
        <div v-for="werk in werke" :key="werk.uid">
            <NuxtLink :to="'/' + werk.uid">
                Test
            </NuxtLink>
        </div>

</template>

The link to the dynamic page [kunstwerke] renders fine in the frontend but if I click it I get an error in the chrome console. If I open it in a new tab it loads with no problem. The error when I click relates to the new site:

[kunstwerke].vue:9 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'titel')

On the dynamic site [kunstwerke] there is a title that also uses prismic data. It seems like the is not fully run when I click on the [kunstwerke] link?

The [kunstwerke] dynamic site is set up like this:

<script setup>
    const route = useRoute()
    const name = route.params.kunstwerke;
    const { client } = usePrismic()
    const { data: werk } = await useAsyncData('werk', () => client.getByUID("werk", name))
    if (!(werk.value)) {
     throw createError({ statusCode: 404, statusMessage: 'Page Not Found' })
    } 

</script>

<template>
    <div class="container container-werk">
        <span>{{ werk.uid }}</span>
        <prismic-rich-text :field="werk.data.titel" />
        <prismic-rich-text :field="werk.data.beschreibung" />


       <slider />
    </div>
</template>

The error seems to relate to the prismic data as it doesn't seem to able to load it. What am I missing here? If I link manually to one of the [kunstwerke] page or open the NuxtLink in a new tab it works.

Any ideas?

edit: Also if I use just a normal a-tag and not NuxtLink it works fine?

Why aren't you using the Prismic link component?

This will correctly generate your link from your document object if you have your route resolver/link resolver setup correctly.

<PrismicLink :field="werk">test</PrismicLink>

Thanks @jake I'm trying this right now. I have two problems though:

  1. In nuxt.config.ts I get an error if I want to add the apiOptions:
export default defineNuxtConfig({

   modules: ['@nuxtjs/prismic'],
   prismic: { 
      endpoint: 'portolio-feierabend',
      apiOptions: {
         // example resolving documents with type `page` to `/:uid`
         routes: [
           {
             type: 'homepage',
             path: '/'
           }
         ]
       }


},
   css: ["~/assets/css/styles.css"]

})

If I leave out defineNuxtConfig I don't get that error.
Type '{ endpoint: string; apiOptions: { routes: { type: string; path: string; }[]; }; }' is not assignable to type 'Partial<PrismicModuleOptions>'.\n Object literal may only specify known properties, and 'apiOptions' does not exist in type 'Partial<PrismicModuleOptions>'.",

  1. If I use PrismicLink I never get a clickable link. There is no href. I try it like this:
<div v-for="werk in werke" :key="werk.uid">
    <PrismicLink :field="werk">test</PrismicLink>
</div>

Any ideas?

In Nuxt3 the Prismic config is slightly different. clientConfig instead of apiOptions.

export default defineNuxtConfig({
    modules: [
        '@nuxtjs/prismic'
    ],
    prismic: {
        endpoint: 'https://repo.cdn.prismic.io/api/v2',
        clientConfig: {
            routes: [
                {
                    type: 'custom_name',
                    path: '/:uid/'
                }
            ]
        }
    },
...

Prismic link will show a blank link/no link when it can't generate the link, which is expected till your route resolver is working.

Hope this helps.

Hey @jake

Thanks that worked to show the correct and clickable links. Unfortunately Now I'm still having the same problem from my original question. The link only open in a new tab. With a click I still get the same error:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'titel')

Which chrome says is happening on the dynamic page. They only don't work with these links though. Normally it works fine. Could there be a problem with loading the same data on a component and a page it links to? Or is it somehow a problem that I create these dynamic pages with the route.params.uid?

This is the code of the dynamic page again:

<script setup>
    const route = useRoute()
    const name = route.params.uid;
    const { client } = usePrismic()
    const { data: werk } = await useAsyncData('werk', () => client.getByUID("werk", name))
    if (!(werk.value)) {
     throw createError({ statusCode: 404, statusMessage: 'Page Not Found' })
    } 

</script>

<template>
    <div class="container container-werk">
        <span>{{ werk.uid }}</span>
        <prismic-rich-text :field="werk.data.titel" />
        <prismic-rich-text :field="werk.data.beschreibung" />


       <slider />
    </div>
</template>

you're always expecting titel to be available on the object when the view is requested but the data for that view hasn't loaded yet.

In a non TS world I would have my setup like this:

<script setup>
...
const page = werk.data || false
...
</script>
<template>
    <div v-if="page" class="container container-werk">
        <span>{{ werk.uid }}</span>
        <prismic-rich-text v-if="page.titel" :field="page.titel" />
        <prismic-rich-text v-if="'page.beschreibung"  :field="page.beschreibung" />
       <slider />
    </div>
</template>

Thanks again @jake. I know, Typescript is something to learn soon. But while your suggestion removed the error and the pages load, the prismic data in the v-if="page" statement still doesn't. It only appears after a page refresh. I'm not entirely sure why it is not updating. I tried it with a v-else loading div, but then it's only that div forever.

edit:

I dug a bit deeper and it seems that useAsyncData loads all pages of the type "werk" when I open the page through the prismicLink. It is like "name" is not read at that point. After reload the right data is loaded. I'll try to figure out how I can fix that.

You will need to give your useAsyncData a unique ID. In this case use your UID name

await useAsyncData(name, () => client.getByUID("werk", name))

1 Like

Yes you're absolutely right. Thanks a lot for all of your help!

1 Like

NP, glad I could have helped. :slight_smile:

1 Like