Skip to content

Instantly share code, notes, and snippets.

@izzygld
Last active July 18, 2023 17:04
Show Gist options
  • Save izzygld/287aa48a90d170dabd9ba479196ea695 to your computer and use it in GitHub Desktop.
Save izzygld/287aa48a90d170dabd9ba479196ea695 to your computer and use it in GitHub Desktop.
WP-Graphql Nav Menu Documentation

WP Grahql - Nav Menu

Implements navigation menu support with two new types: Menu and MenuItem. Each have singular and plural root queries. MenuItems are connected to both Menus and to themselves—this allows for the implementation of childItems (hierarchical nav menu queries):

Query{
  menus( location: MAIN ) {
    edges {
      node {
        id
        menuItems {
          edges {
            node {
              id
              label
              url
              title
              target
              linkRelationship
              description
              childItems {
                edges {
                  node {
                      cssClasses
                      description
                      id
                      label
                      linkRelationship
                      menuItemId
                      target
                      title
                      url
                      connectedObject {
                          ... on Post {
                            id
                            title
                            content
                          }
                        }
                      }
                    }
                  }
                  connectedObject {
                    ... on Post {
                      id
                      title
                      content
                    }
                  }
                }
              }
            }
          }
        }
      }
    }

MenuItems can also be queried directly with an id or location:

{
  menuItems( first: 1 where: { location: FOOTER } ){    
    edges {
      node {
        id
        connectedObject {
          ... on Post {
            id
            title
            content
          }
        }
      }
    }
  }
}

Menu locations are implemented as an Enum. This allows the schema to communicate which menu locations have been registered for the current active theme.

The connectedObject field returns a Union of types that can be added the nav menus: post types, taxonomy terms, and custom links (itself a MenuItem). This provides consistent communication of the information about a nav menu object (which is usually the thing the user is trying to query).

MenuItems are tightly tied to the hierarchy of their Menu (parent-child relationships are stored in post meta), so we cannot resolve MenuItems if we cannot resolve the Menu that they belong to. In other words, this query returns an empty array:

{
  menuItems {
    edges {
      node {
        id
      }
    }
  }
}

for menu post formats:

The "type" of a WP nav menu item is stored in the post meta key _menu_item_type and describes whether the menu item points to a post or a term or is a custom link. In WPGraphQL-speak, it describes the type of the object that is connected to the menuItem; in the query below, it informs the __typename of the connectedObject field:

  menuItems(
    where: {
      location: MY_MENU_LOCATION
    }
  ) {
    nodes {
      connectedObject {
        __typename
        ... on Post {  # post, _menu_item_type = post_type
          title
        }
        ... on Book {  # custom post type, _menu_item_type = post_type
          title
        }
        ... on Category {  # tax term, _menu_item_type = taxonomy
          name
        }
        ... on MenuItem {  # "custom link", _menu_item_type is empty
          title
        }
      }
    }
  }
}

You can see that the meta key value of _menu_item_type quickly becomes irrelevant, because it not connected to WPGraphQL's type system. What you're really asking for is a way to filter the menuItems by the __typename of their connectedObject.

You can do that manually, of course, once you get the results back. Implementing it as a query arg, however, would mean either (a) using a post meta query (non-starter, too expensive), or (b) getting all of the menu items and then filtering them on the WPGraphQL side.

I'm not sure if doing (b) makes sense or might lead to issues (e.g., complicated pagination). Under the hood, we're using wp_get_nav_menu_items to the get the menu items so it's not straightforward to combine query args.

So this needs some investigation. In the meantime, I can recommend filtering by __typename on the consuming side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment