Tailwind Logo

Create a breadcrumb list component

XM CloudHeadless SXA

Published: 2024-03-06

Applying the behavior of the previous LinkList, I would like to create a breadcrumb list component this time.

Create an empty component

First, we want to create an empty component. The wizard makes it easy to create the initial configuration.

As a different procedure from the above page,

  • component name as Breadcrumb
  • The component file is src\components\Navigation\Breadcrumb.tsx
  • Other properties are not set
  • Open Properties after Add item is No
  • Datasource Template should be deleted (template items are not needed either)

You are now ready to go.

Preparing GraphQL

The last time I did this, I was getting a list of linked lists one item down, but this time I want to go back and get the navigation title from the corresponding item. The actual query is as follows

GraphQL
fragment breadcrumbFields on Item {
    field(name: "NavigationTitle") {
      ... on TextField {
        value
      }
    }
  url {
    path
  }
}
query BreadcrumbQuery($contextItem: String!, $language: String!)  {
  # Assume the item id is available on the page
  item(path: $contextItem, language: $language) {
    ancestors(
      hasLayout: true
      includeTemplateIDs: "B4283FEF-AE4E-4992-82E7-33B170C7A7DE"
    ) {
      ...breadcrumbFields
    }
  }
}

The GUID in includeTemplateIDs specifies the item ID of the Page template.

breadcrumb06.png

For this, specify the following Query Variables.

JSON
{
  "contextItem": "74010881-DF60-4FB0-973A-C109959E2E9B",
  "language": "en"
}

This contextItem item should specify the ID of the item. As a result, the following Json data can be obtained

JSON
{
  "data": {
    "item": {
      "ancestors": [
        {
          "field": {
            "value": "Resource"
          },
          "url": {
            "path": "/resource"
          }
        },
        {
          "field": {
            "value": "Home"
          },
          "url": {
            "path": "/"
          }
        }
      ]
    }
  }
}

We were able to get the Navigation Title and Path of the item from the corresponding item to Home. Copy this query into GraphQL.

breadcrumb01.png

Change the code of a component

In this case, I would like to put in some code to check if it works as a breadcrumb list. First, we will define an Interface that can handle the returned Json data.

TypeScript
interface Ancestor {
  field: {
    value: string;
  };
  url: {
    path: string;
  };
}

interface Fields {
  data: {
    item: {
      ancestors: Ancestor[];
    };
  };
}

Then rewrite the function call section.

TypeScript
type BreadcrumbProps = {
  params: { [key: string]: string };
  fields: Fields;
};

export const Default = (props: BreadcrumbProps): JSX.Element => {

Now it will work with the GraphQL data defined in the Json Rendering item. Also, to verify that the component is working correctly, add the following code

TypeScript
import { useSitecoreContext } from '@sitecore-jss/sitecore-jss-nextjs';

Finally, rewrite the behavior of the contents of Default, already called out above using BreadcrumbProps, as follows

TypeScript
export const Default = (props: BreadcrumbProps): JSX.Element => {
  const data = props.fields?.data;
  const { sitecoreContext } = useSitecoreContext();

  if (data.item.ancestors.length > 0) {
    return (
      <div className="component-content">
        <div>Item OK </div>
        <div>id: {sitecoreContext.itemId}</div>
      </div>
    );
  }

  return (
    <div className="component-content">
      <div>No Item </div>
      <div>id: {sitecoreContext.itemId}</div>
    </div>
  );
};

Now you are ready to go. If you have retrieved the data, you should see the text Item OK and the item ID of the Sitecore item on that page.

breadcrumb02.png

Referring to the item ID, we can see that we are getting the value correctly.

breadcrumb03.png

We have confirmed that the data has been acquired. We now need to prepare a function to display the acquired data as a list.

TypeScript
function generateBreadcrumbList(ancestors: Ancestor[]): JSX.Element {
  // Iterate through ancestors and generate li elementss
  const ancestorListItems = ancestors.map((ancestor: Ancestor, index: number) => {
    return (
      <li key={index}>
        <a href={ancestor.url.path}>{ancestor.field.value}</a>
      </li>
    );
  });

  // Wrap the list items with ul tags and return the JSX element
  return <ul>{ancestorListItems}</ul>;
}

Rewrite as follows

typescript if (data) { return <div className="component-content">{generateBreadcrumbList(data.item.ancestors)}</div>; }

The following could be created

breadcrumb04.png

For a breadcrumb list, the reverse order is better, so rewrite the function as follows

TypeScript
function generateBreadcrumbList(ancestors: Ancestor[]): JSX.Element {
  const reversedAncestors = ancestors.reverse();

  const ancestorListItems = reversedAncestors.map((ancestor: Ancestor, index: number) => {

As a result, the following was displayed.

breadcrumb05.png

Allow styles to be applied

Add the following code to allow Style settings for the resulting component.

TypeScript
export const Default = (props: BreadcrumbProps): JSX.Element => {
  const data = props.fields?.data;
  const styles = `component breadcrumb ${props.params.styles}`.trimEnd();
  const id = props.params.RenderingIdentifier;

  const { sitecoreContext } = useSitecoreContext();

  if (data) {
    return <div className="component-content">{generateBreadcrumbList(data.item.ancestors)}</div>;
  }

  return (
    <div className={styles} id={id ? id : undefined}>
      <div className="component-content">
        <div>No Item </div>
        <div>id: {sitecoreContext.itemId}</div>
      </div>
    </div>
  );
};

Now, when we want to process the breadcrumb list, we can add stylesheet processing by specifying breadcrumb. We could also use styles to retrieve the style data that the CMS side has.

Summary

This time, I created a sample breadcrumb list to be created with Next.js, although it is a long one. In actuality, the data to be covered is obtained using GraphQL, and then passed to the component side, where it is retrieved and processed.

Related article

Tags