#nested pages url

1 messages · Page 1 of 1 (latest)

dusty flame
#

Hi, hope someone can point me in the right direction. I'm trying to create a child page from a parent page.

Parent
--> Child

In order to do so, I've used the nested-docs plugin. In my Child page, I've set the parent to my Parent page. Granted, the relationship is created however I can't seem to make it work where I should be able to access the page using the nested url which is "{baseUrl}/parent/child". Is there additional config changes that I need to do for this? Thanks!

simple boneBOT
pine shuttle
#

You are talking about accessing/getting it via the API in your frontend?

#

We call the API like this:
${BASE_URL}/api/pages?where[slug][equals]=${slug}&locale=${locale}

dusty flame
#

Not really. Just accessing the page in a nested url format. So, in the browser url, I enter localhost:3000/parent/child <- I'm assuming I should be able to open the page using this. What's happening right now though is even if I created a Child page with a Parent, the page is created as if it doesn't have a parent and I can open that page with localhost:3000/child instead.

pine shuttle
#

yeah, but how do you fetch the page data?

#

in the working szenario

#

Because you cant just pass the whole path the the API and will get the result. You will have to split it

dusty flame
#

Ah I see. After seeing the fetchPage I think I get it, I'll see if it works. 🙏

pine shuttle
#

yeah... I had the same problem understanding the logic in the beginning 😅

proud snow
#

I'm currently thinking about same scenario, but I still dont get it guys. In fetchPage they only taking last url segment right? so from "/parent/child" it would take "child", fetch correctly because child exists and display page. But I can't see where we check if child is indeed descendant of parent, maybe I'm missing something.

pine shuttle
#

that is handled in this part:

#
const pagePath = `/${slugSegments.join('/')}`

const page = data.Pages?.docs.find(({ breadcrumbs }: Page) => {
  if (!breadcrumbs) return false
  const { url } = breadcrumbs[breadcrumbs.length - 1]
  return url === pagePath
})
#

Because the full path "parent/child" should be present as the last breadcrumb element created from the nestedDocs plugin

#

and only if this is found, the page is returned

#

so the page wont be returned for {domain}/child/ . Only for {domain}/parent/child/

proud snow
#

For now I came up with solution:
Add field "prefix" which will be optional on some collections, then include it in generating URL like so : generateURL: (docs) => docs.reduce((url, doc) => `${doc?.prefix}/${url}/${doc.slug}`, ""),

Now I should be able to use nestedDocs for pages, blog posts and products accordingly with their own prefixes.

edit: I'm trying to come up with another solution.

pine shuttle
#

In next we solved this with corresponding routes/folders and custom "fetch" functions for each collection type

dusty flame
#

I've manage to do what I want by updating my getStaticProps and getStaticPaths. Thank you @pine shuttle!

I do have a question though. I'm pretty new to next and ssg so I'm not sure what's the right approach. Right now, props are fetched and passed to my component blocks in the slug.tsx and it's all good. What if I have a collection that I want to passed to one of my pages. Is fetching it in the slug.tsx only when the user is in that page/slug the right approach?

pine shuttle
#

Are you using pages or app router in Next JS?

#

In the app router you can just do it in the function itself, in pages router you would probably use getServerSideProps

#

Here ist how we did it in an pages router project with a simpler logic without nesting:

import { fetchPage } from "@/scripts/fetch";
import { Page } from "@/types/payload-types";
import Custom404 from "../404";
import PageView from "../../views/pageView";

interface IProps extends Page {
  data: Page | null;
}

export default function Page(props: IProps) {
  if (!props.data) return <Custom404 />;
  return <PageView data={props.data} />;
}

export const getServerSideProps = async ({ params }: { params: any }) => {
  let slug = params?.slug;
  if (Array.isArray(slug)) slug = slug.join("/");

  try {
    const response = await fetchPage<any>(
      `${process.env.NEXT_PUBLIC_CMS_URL}/api/pages?where[slug][equals]=${slug}`,
    );
    if (!response.data.docs.length) {
      return { props: { data: null } };
    }

    const page: Page = response.data.docs[0];
    return { props: { data: page } };
  } catch (err: any) {
    console.error(err.message);
  }
};
dusty flame
#

Thanks @pine shuttle, you're answers help me go the right direction. 🙏

woeful talon
#

is there a updated way to do this I am building over website template and not able to figure it out how to create nested pages , I used nested docs plugin but the page is still publishing on website.com/child