Modular content using same block type as child

Hello,

Using DatoCMS, I started implementing a block called LayoutBlock that behaves exactly like flexbox:

The block has very similar properties and at last, the blocks property which is a modular content allowing various type of other blocks including a LayoutBlock.

I want to use it for a page model.
The page model consist of having an initial layout block and in the block section add other blocks as children.

Now, I face an issue when querying this page with GraphQL.

I’ve tried defining a fragment

fragment LayoutFieldsFragment on LayoutBlockRecord {
    id
    __typename
    // various properties...
    blocks {
        ...HeaderFieldsFragment
        ...ParapgraphFieldsFragment
        ...LayoutFieldsFragment **<= Issue here**
    }
  }

The problem is when I include the LayoutFieldsFragment within itself, I get an error 500.

I would like to know if this is actually possible to achieve. If DatoCMS is flexible enough to nest the same block within itself.
Implementing this would give a very flexible way to the content editors when building pages and less coding for engineers.

I’ve read that maybe this is not possible given the GraphQL design and that I should specify a level of depth in LayoutFieldsFragment. But I find this ugly.

Thank you in advance for your help!

Hi @arthur.feral, and welcome to the community!

Unfortunately, as you noticed, recursive queries like that aren’t allowed in the GraphQL spec: GraphQL Recursive Query with Fragments | Hash Interactive

But you can do something pretty similar, and just a bit uglier:

query MyQuery {
  allPages {
    id
    _modelApiKey
    title
    blocks {
      ...LayoutFieldsFragment
      blocks {
        ...LayoutFieldsFragment
        blocks {
          ...LayoutFieldsFragment
          blocks {
            ...LayoutFieldsFragment
          }
        }
      }
    }
  }
}

fragment LayoutFieldsFragment on LayoutBlockRecord {
  id
  _modelApiKey
  title
}

Which returns:

{
  "data": {
    "allPages": [
      {
        "id": "EHmArlTgR9uCzKmvN-pdfw",
        "_modelApiKey": "page",
        "title": "Page Title",
        "blocks": [
          {
            "blocks": [
              {
                "blocks": [
                  {
                    "blocks": [],
                    "id": "Twm7o0AsTnaXu8DK2hGfLg",
                    "_modelApiKey": "layout_block",
                    "title": "Third-level layout block"
                  }
                ],
                "id": "M6WJp8FWQq6lyVUa8j7aVA",
                "_modelApiKey": "layout_block",
                "title": "Second-level layout block"
              }
            ],
            "id": "MAidaoddRxme-nRaeXSqwQ",
            "_modelApiKey": "layout_block",
            "title": "Top-level layout block"
          }
        ]
      }
    ]
  }
}

You can have more layers of blocks {} than you actually need, just to ensure you can query up to that depth of nesting. But you can’t make it infinite.


And just so you know, another option would be to use our Content Management REST API, which can also fetch nested blocks when you specify the nested: true parameter:

GraphQL is great when you want to specify exact fields to fetch across different relationships. But for expanding nested blocks, you do unfortunately have to use either the uglier query or the REST API instead. Sorry about that!