Search code examples
graphqlgridsome

Query an array with unstructured objects on GraphQL


I'm trying to use GraphQL to query an unstructured array with objects in Gridsome. It is currently looking very messy and it feels like there should be a better way to do this.

The data that gets loaded into GraphQL from the CMS looks like this:

{
    title: "Homepage",
    top_image: "imgurl.jpg",
    page_builder: [
             {
                 type: "slider",
                 field: "data example",
                 different_field: "data example"
             },
              {
                 type: "call_to_action",
                 field_for_cta: "data example",
                 different_cta_field: "data example"
             }
    ]
}

As you can see the objects in page_builder will have different fields depening on how the client is building this section.

When I try to query this in GraphQL. It will become very messy:

<page-query>
query {
  data: pages(path: "/pages") {
    title,
    top_image,
    page_builder {
      type,
      field,
      different_field,
      type,
      field_for_cta,
      different_cta_field

      #this list will have way more fields depending on all the page builder elements

    }
    }
  }
</page-query>

Is there a way to organize this fields by type and only return the fields of this specific type?


Solution

  • Assuming gridsome supports fragments, you can do something like this:

    <page-query>
    query {
      data: pages(path: "/pages") {
        title,
        top_image,
        page_builder {
          ...A @include(if: $includeA)
          ...B @include(if: $includeB)
          ...C @include(if: $includeC)
        }
      }
    }
    
    # Note: Replace PageBuilderType with appropriate type
    fragment A on PageBuilderType {
      # your fields here
    }
    fragment B on PageBuilderType {
      # your fields here
    }
    fragment C on PageBuilderType {
      # your fields here
    }
    </page-query>
    

    You can then define the variables when calling createPage as shown here:

    api.createPages(({ createPage }) => {
        createPage({
          path: '/my-page',
          component: './src/templates/MyPage.vue',
          queryVariables: {
            includeA: someCondition,
            includeB: someCondition,
            includeC: someCondition,
          },
        })
      })
    }