linkResolver and nested paths

Hey,

I’m building a complete guide for a website, with next JS and dynamic page.

I will have an architecture like this : mydomain.com/hub/chapter/article

In an article, I have a content relationship to a chapter, and a chapter has its own content relation ship to hub.

In an article, I have a RichText element where we can have links to other Prismic document, for example a chapter or an article. Assume we want to go mydomain.com/hub/chapter/article2, for this need I add a relationship content in RichText editor.

Now if I need to make a correct link, I need to use linkResolver on RichText component.

But how to rebuild the full path to article page for exemple ? LinkResolver have only few attributes and it seems impossible to make a async call to get all datas I need to rebuild my specific path, and it seems weird to make a thing like this.

Thanks

Hi Yoaan,

Unfortunately it’s not possible to do more than one level deep of nested threads at the moment.

That is to say you could have mydomain.com/category/dynamic-uid in the link resolver, by using fetchlinks:
https://prismic.io/docs/reactjs/query-the-api/fetch-linked-document-fields
NOTE: You must be using V2 of the api for this to work.

but not the more complex mydomain.com/parent-category/category/dynamic-uid .

Although we are working on a new more intelligent link resolver, for the Static SSR technologies like Nuxt, Next & Gatsby, that would allow you to easily create complex nested URLs like this. I will be sure to keep you updated with the progress of this.

For now one solution that could work, though not perfect, is to use the document tags to create the third level, so in Prismic your tag on the document would be ‘hub’ then in the link resolver you could use that to create the third level.

if (
  doc.tags.includes('hub')
) {
  return `/hub/${doc.data.relationlink.data.name}/${doc.uid}`
} 

Then you would repeat this in the linkresolver for every parent category. I know it’s not great but until we release the new resolver it’s a good solution.

Let me know if you have any further questions about this.

Thanks.

Hey Phil,

Thanks for your answer. Infortunately, my hub and chapter are slug too and dynamic too :slight_smile:

And I already use fetchLinks, but I’m not sure that I got my chapter_link from my article in LinkResolver, I will check for this point.

Tag can be usefull, I can just add my tag which is same as my hub slug to simulate one level, not perfect :frowning:

Just check, I got my chapter_link in my article when I fetch one article.

But I don’t get it in my LinkResolver which analyze my content from my RichText element. Or am I missing something ?

Ah sorry I wasn’t clear. Your content relationship field needs to be a unique field in the top level of your document, you can’t get the content through a link in a Rich Text field.
https://prismic.io/docs/reactjs/query-the-api/query-by-content-relationship

Yes that’s my main problem, not accessing through a link in a Rich Text field :frowning:

Unfortunately that won’t be possible then.

@Phil - did you all ever make an improved resolver? This would be very useful.

Hi John,

Unfortunately not, we’ve have only managed to implement this for our Nuxt users so far. Although this is something that we are working on for Next.js users and hope to release it in Beta in the near future.

Once we have any update about this we’ll update you here.

Thanks.

@Phil - thanks. I’ve come up with creative solutions for this issue on the project I’m working with.

1 Like

We’d be happy to see your solutions if you feel comfortable sharing?

Is there any technical detail on how this was implemented in Nuxt.js and not next.js. Is this something we could take a look at porting over to Next.js ourselves?

Hi Markaðsdeild,

Unfortunately this is not something that you can port yourselves as it’s something that is implemented specifically on Slice Machine repositories and can only work for Nuxt projects for now, the technical docs for that are below.

Although the team is going to hopefully make this possible for Next soon.

So for now for other users the only way to do nested paths is how I described above with a content relationship field and to get that data in the linkresolver:

if (
  doc.tags.includes('hub')
) {
  return `/hub/${doc.data.relationlink.data.name}/${doc.uid}`
} 

I’ve got ideas I’m working through but very disappointed with your documentation. This platform is highly unique and poorly documented.

Hey John,

I’m sorry to see you feel that way. We are working on improving our documentation so that we can make it more intuitive to find information. Is there anything else other than nested paths that you need help with?

There is a work around that you can do until it’s better supported but you can process the RichText data before you return it from your prismic service.

For example if you have a RichText that has a Link to an article and that article is using a two level link where the first part of the link is based on some data within the article the below code can update the hyperlink span in the Richtext data with a “resolvedUrl”.

/**
 * Parses the RichText value from Prismic and finds each hyperlink item and resolves the link
 */
static async resolveDynamicLinksInRichText(richText) {

  return Promise.all(richText.map(async (richTextElement) => {
    if (richTextElement.spans) {
      const spans = await Promise.all(richTextElement.spans.map(async (span) => {
        if (span.type === 'hyperlink') {
          const data = await this.resolveDynamicLink(span.data);
          return { ...span, data };
        } else {
          return span;
        }
      }));
      return { ...richTextElement, spans };
    } else {
      return richTextElement;
    }
  }));
}

/**
 * Resolves links that have multiple levels that is not currently possible in Prismic.
 */
static async resolveDynamicLink(doc) {
  if (doc.link_type && doc.link_type === 'Web') {
    return doc;
  }

  switch (doc.type) {
    case 'blog_post':
      const post = await this.getBlogPostByUid(doc.uid);
      return { ...doc, resolvedUrl: linkResolver(post) };
    default:
      return doc;
  }

}

An example of using it would be something like:

const resolvedRichtext = await resolveDynamicLinksInRichText(doc.rich_text_field)

Then in your linkResolver method you can check the existence of the resolvedUrl and return that or fallback on your normal link resolving.

1 Like