Using Modular fields with Gatsby

Having a bit of a tough time wrapping my head around Modular fields and getting that data on my Gatsby site.

I’ve set up a Modular Content block as seen on this page (https://www.datocms.com/docs/content-delivery-api/modular-content) and I can successfully query the data in my graphql playground like:

          content {
              ... on DatoCmsBlogPostTextBlock {
                  text
              }
          }

, but including _modelApiKey throws this error.
Cannot query field “_modelApiKey” on type “DatoCmsBlogPostTextBlock”.

A similar page (https://www.datocms.com/docs/static-generators/other-ssg/modular-content --> BTW, what are the other SSG we’re talking about?) has mention of a dato.config.js file. I don’t have that file so maybe that’s the cause for error?

In my work.js template (using the gastby/datocms template --> https://www.gatsbyjs.org/starters/datocms/gatsby-portfolio/) I’ve added the query above and I’m trying to get my data on the website like:

{data.datoCmsWork.content.text}

Now, I think the API key basically IDs the proper field and the way to get it on the site probably involves a .map() to render out whatever’s in the modular block.

I’ve been looking but can’t find documentation on this and was hoping to get some help and maybe help others looking for this info too.

This is my first post here. Fairly new in the DatoCMS/Gatsby world. Hi all!
Let me know if there’s any more details I can provide.
Thanks! :slight_smile:

hello @consolecmnd and welcome to Community :slight_smile:

to get the API key of a modular content you can have a look here: https://github.com/datocms/gatsby-source-datocms#modular-content-fields

you need to extract

model { apiKey }

And to get some usage examples you can start from these:


Let me know if you need more info!

Cheers

Hi Mat, thanks for providing the links.

My site is based off of the Gatsby Portfolio and I looked through the code of the snipcart-gatsby-demo and I’m not seeing any usage examples of the model { apiKey }.

Trying again the example from https://github.com/datocms/gatsby-source-datocms#modular-content-fields

My query looks like

export const query = graphql`
  query WorkQuery($slug: String!) {
    datoCmsWork(slug: { eq: $slug }) {
      content {
        ...on DatoCmsBlogPostTextBlock {
          model { apiKey }
          text
        }
      }
    }
  }

And in the same file, I’m trying to get output with:

     {
       data.datoCmsWork.content.map((block) => (
         <div key={block.id}>
           {
             block.model.apiKey === 'text' &&
               <div>{block.text}</div>
           }
         </div>
       ))
     }

Results in an error reading:
TypeError: Cannot read property 'apiKey' of undefined

error --> <div key={block.id}>

To try to get the apiKey from GraphQL I added the following to the layout.js file.

     allDatoCmsModel {
       edges {
         node {
           apiKey
         }
       }
     }

Added to the LayoutQuery query to try and create a global variable but not getting any output from my populated Modular fields.

I can see my data in the GraphQL Playground when I run the queries, but I’m having trouble translating that to the site.

In the future could the base DatoCMS/Gatsby portfolio starter template be possibly updated to include an example of Modular content in use?

Sorry for the long post.

because you have two different blocks that can be part of the content, which means that you are getting two objects back, one of which doesn’t have {model {apiKey}}

this is your content now:

"content": [
            {
              "model": {
                "apiKey": "blog_post_text_block"
              },
              "text": "Lorum Ipsum Lorum Ipsum Lorum Ipsum Lorum Ipsum Lorum Ipsum Lorum Ipsum ",
              "__typename": "DatoCmsBlogPostTextBlock"
            },
            {
              "__typename": "DatoCmsBlogPostQuoteBlock"
            }
          ]

does that explain what I mean? You should add one fragment for each type of block to handle all the options, like this:

content {
        ... on DatoCmsBlogPostTextBlock {
          model {
            apiKey
          }
          text
        }
        ... on  DatoCmsBlogPostQuoteBlock{
          model {
            apiKey
          }
        }
      }

Hi @mat_jack1, thanks again for the advice. It was enough for me to get things rolling.

I think the thing I was hung up on was that the Model ID provided in the CMS is actually the apiKey. Not sure why, but I didn’t see the connection there.

Once I saw that matching up in the console log it wasn’t much trouble for the rest to follow.

If anyone finds this in the future, here’s roughly what you can do.

  query WorkQuery($slug: String!) {
    datoCmsWork(slug: { eq: $slug }) {
      content {
        ...on DatoCmsBlogPostTextBlock {
          model { apiKey }
          text
        }
        ...on DatoCmsBlogPostQuoteBlock {
          model { apiKey }
          quote
          author
        }
      }
    }
  }

Then to output:

<div>
  {
    data.datoCmsWork.content.map((block) => (
      <div key={block.id}>
        {
          block.model.apiKey === 'blog_post_text_block' &&
            <div>{block.text}</div>
        }
        {
          block.model.apiKey === 'blog_post_quote_block' &&
          <div>{block.quote}<br/>{block.author}</div>
        }
      </div>
    ))
  }
</div>

Cheers and thanks again!

1 Like

Hey @consolecmnd,

I’m also trying to use modular content fields for my website and I’ve tun into a slightly different issue.

I see inside your content field you have a modular field titled text. How do you use this field? Do you just use it for paragraph text and nothing more of does it contain all kinds of headings, links etc?

I’m trying to use a modular text field to parse markdown but because the graphQL endpoint only gives a string, my markdown doesn’t parse.

Any help would be my holy appreciated.

Hey @consolecmnd ,

I was wondering if anyone knows how to get modular content to be included in the statically generated build script? The modular content which loops through and gets rendered by the correct component based on the apiKey for some reason does not get included in my builds.