chapter-three / next-drupal

Next.js for Drupal has everything you need to build a next-generation front-end for your Drupal site: SSG, SSR, and ISR, Multi-site, Authentication, Webforms, Search API, I18n and Preview mode (works with JSON:API and GraphQL).
https://next-drupal.org
MIT License
627 stars 174 forks source link

Rendering taxonomy term page #486

Closed Sanci91 closed 1 year ago

Sanci91 commented 1 year ago

Hi, I'm trying to show a tag term page. As example I created a url pattern in admin/config/search/path/patterns/add for taxonomy terms of tags vocabulary as tags/[term:name]. Then I added in the pages folder a file named term.tsx with the following code:

import { GetStaticPathsResult, GetStaticPropsResult } from "next"
import Head from "next/head"
import { DrupalTaxonomyTerm } from "next-drupal"

import { drupal } from "lib/drupal"
import { TaxonomyTermTags } from "components/taxonomy_term--tags"
import { Layout } from "components/layout"

const RESOURCE_TYPES = ["taxonomy_term--tags"]

interface TaxonomyTermPageProps {
  resource: DrupalTaxonomyTerm
}

export default function TaxonomyTermPage({ resource }: TaxonomyTermPageProps) {
  if (!resource) return null
  return (
    <Layout>
      <Head>
        <title>{resource.title}</title>
        <meta name="description" content="A Next.js site powered by Drupal." />
      </Head>
      {resource.type === "taxonomy_term--tags" && <TaxonomyTermTags term={resource} />}
    </Layout>
  )
}

export async function getStaticPaths(context): Promise<GetStaticPathsResult> {
  return {
    paths: await drupal.getStaticPathsFromContext(RESOURCE_TYPES, context),
    fallback: true,
  }
}

export async function getStaticProps(context): Promise<GetStaticPropsResult<TaxonomyTermPageProps>> {
  const path = await drupal.translatePathFromContext(context)

  if (!path) {
    return {
      notFound: true,
    }
  }

  const type = path.jsonapi.resourceName
  let params = {};
  if (type === "taxonomy_term--tags") {
    params = {
      include: "name,path",
    }
  }

  const resource = await drupal.getResourceFromContext<DrupalTaxonomyTerm>(path,
    context,
    {
      params,
    }
  )

  // At this point, we know the path exists and it points to a resource.
  // If we receive an error, it means something went wrong on Drupal.
  // We throw an error to tell revalidation to skip this for now.
  // Revalidation can try again on next request.
  if (!resource) {
    throw new Error(`Failed to fetch resource: ${path.jsonapi.individual}`)
  }

  // If we're not in preview mode and the resource is not published,
  // Return page not found.
  if (!context.preview && resource?.status === false) {
    return {
      notFound: true,
    }
  }

  return {
    props: {
      resource,
    },
  }
}

And also a new component called taxonomy_term--tags.tsx with the following code:

import { DrupalTaxonomyTerm } from "next-drupal"

interface TaxonomyTermTagsProps {
  term: DrupalTaxonomyTerm
}

export function TaxonomyTermTags({ term, ...props }: TaxonomyTermTagsProps) {
  return (
    <article {...props}>
      <h1>{term.name}</h1>
      {/* {console.log(term)} */}
    </article>
  )
}

I'd expect to visit http://localhost:3000/tags/xyz and find the title of the term, but it is not showing anything. Can you help me? I'm not finding any guide to how show different entities rather than nodes on the documentation.

shadcn commented 1 year ago

This is correct. The following code is fetching the term entity only.

const resource = await drupal.getResourceFromContext<DrupalTaxonomyTerm>(path,
  context,
  {
    params,
  }
)

If you want to fetch articles tagged by this term you need to use something like this:

const nodes = await drupal.getResourceCollectionFromContext(
  "node--article",
  context,
  {
    params: {
      "filter[field_tags.id]": resource.id,
    },
  }
)

This will fetch all articles tagged with the term. Which you can then pass as props to render.

apmsooner commented 1 year ago

Closing this issue as a viable solution is provided.