Help Structuring Mega Menus with Prismic

I’m currently working on a large e-commerce site and have integrated Prismic for dynamic content and various site configurations so we don’t need to hard-code.

Problem:
We have a working mega menu that contains hard-coded content, but upon attempting to move this task to Prismic, we’ve found that Prismic's lack of deeply nested fields and repeatable groups of content within slices… it’s proven very difficult to strategize integration.

Needed Structure:

  • Navigation (singleton type)
    • Navigation Item (repeatable)
      • Label (key text)
      • Label Path (key text)
      • MegaMenu (optional, non-repeatable)
        • Column (repeatable)
          • Label (key text)
          • Label Path (key text)
          • Menu (group)
            • Menu Item (repeatable)
              • Label (key text)
              • Label Path (key text)
        • Promos (group)
          • Promo (repeatable)
            • Image (media)
            • Label (key text)
            • Path (key text)

Given we are fairly new to Prismic, we’re running into roadblock after roadblock in creating a Prismic custom type that can accomplish this. Is there a solution or workaround we’re missing?

Thanks

@joshwcorbett There are many ways of modeling this structure. Are you using Slice Machine or the Legacy Builer?

Here's what I suggest. You'll have two Custom Types: Navigation and Mega Menu. Then you'll have Slices for the rest of the Navigation. Let's go over each one.

Navigation will be a singleton where you'll add Slices to link your mega menus:

└── Navigation (singleton)
    ├── label 
    ├── label_path
    └── Navigation Item (Slice)
        └── Repeatable zone
            ├── label
            ├── label_path
            └── mega_menu (Content Relationship)

The Mega Menu would be a repeatable type with two Slices, Column and Promos. The last thing we'd need to resolve is where and which types of links you wanna add to each level. For example, Links to other documents using Content Relationship fields links to the web, or links to media:

└── Mega Menu (Repeatable)
    ├── Column (Slice)
    │   ├── Non-repeatable zone
    │   │   ├── label
    │   │   └── label_path
    │   └── Repeatable zone
    │       ├── label
    │       └── label_path
    └── Promos (Slice)
        └── Repeatable zone
            ├── image
            ├── label
            └── label_path
1 Like

Thanks for this solution! Currently having troubles returning the slices from the mega_menu under each Navigation Item.

// Menu.vue
const {
  data: response,
  error,
  pending
} = await useAsyncData(
  'navigation',
  () => {
    const { client } = usePrismic()
    return client.getSingle(
      'navigation',
      {
        lang: 'en-US',
      }
    )
  },
  { lazy: true }
)
const { body: nav } = response.value?.data || []

As seen here no slices are returned from the above snippet.

// Navigation Structure
- Menu.vue // gets 'navigation' document
  - MenuItem.vue (renders for each Navigation Item) // receives each Navigation Item as a prop
    - Dropdown.vue // receives mega_menu as a prop

Ended up reading into the usage of fetchLinks but to no avail, and am unsure of how predicate can be used in this context should it be an applicable use case.
If it helps, we're using Nuxt 3.

Thanks

Solved by using fetchLinks correctly.

const {
  data: response,
  error,
  pending
} = await useAsyncData(
  'navigation',
  () => {
    const { client } = usePrismic()
    return client.getSingle(
      'navigation',
      {
        lang: 'en-US',
        fetchLinks: 'mega_menu.body'
      }
    )
  },
  { lazy: true }
)
const { body: nav } = response.value?.data || []

For anyone else looking for a solution, note the usage of fetchLinks asking for mega_menu.body

1 Like