👀 See Sanity in action: Watch product demo now →

Rendering nested block content

2 replies
Last updated: Jan 18, 2021
I’m struggling to get nested block content rendering. I have a custom block that itself contains block content.

function ImageBlockLeftSerializer(props) {                                                            
  const img = h('img', {src: getImageUrl({ node: props.node.image, options: props.options})})

  return h('div', {className: 'row'}, [
    h('div', {className: 'col-12 col-md-6 d-flex align-items-center'}, img),
    h('div', {className: 'col-12 col-md-6'},  props.node.text)
  ])
}
for a schema like this:

export default {
  title: 'Block Content',
  name: 'blockContent',
  type: 'array',
  of: [
    // normal stuff
    {
      type: 'imageBlockLeft'
    }
  ]
if I put
props.node.text
through
blockContentToHtml
in my serializer then I get the HTML output as a string but not as HTML. That’s the closest I’ve got. Any ideas?
Custom block definition:

export default {
  name: 'imageBlockLeft',
  title: 'Image Block (Left)',
  type: 'object',
  fields: [
    {
      name: 'image',
      title: 'Image',
      type: 'image',
      validation: Rule => Rule.required()
    },
    {
      name: 'text',
      title: 'Text',
      type: 'blockContent'
    }
  ]
}
Example props:


{
  "node": {
    "_key": "8aadac420e1a",
    "_type": "imageBlockLeft",
    "image": {
      "_type": "image",
      "asset": {
        "_ref": "image-35774cbd8c18717d79503e716e5829dad730a134-407x229-png",
        "_type": "reference"
      }
    },
    "text": [
      {
        "_key": "034bfcfdf0dd",
        "_type": "block",
        "children": [
          {
            "_key": "7cb2dc325caa",
            "_type": "span",
            "marks": [],
            "text": "Test ImageBlockLeft"
          }
        ],
        "markDefs": [],
        "style": "h1"
      },
      {
        "_key": "2739c417f299",
        "_type": "block",
        "children": [
          {
            "_key": "35c1a24c980b",
            "_type": "span",
            "marks": [],
            "text": "Some dummy content in the text attribute of this content type."
          }
        ],
        "markDefs": [],
        "style": "normal"
      }
    ]
  },
  "options": {
    "projectId": "89ig8fee",
    "dataset": "ccblog",
    "imageOptions": {}
  },
  "children": []
}
Jan 18, 2021, 6:35 PM
Solved by using
blocksToHyperScript
rather than
blockContentToHtml
.
Jan 18, 2021, 6:51 PM
The full serializer function:

function ImageBlockLeftSerializer(props) {                                                            
  const img = h('img', {src: getImageUrl({ node: props.node.image, options: props.options})})

  return h('div', {className: 'row'}, [
    h('div', {className: 'col-12 col-md-6 d-flex align-items-center'}, img),
    h('div', {className: 'col-12 col-md-6'},  blocksToHyperScript({ blocks: props.node.text}))
  ])
}

Jan 18, 2021, 6:52 PM

Sanity.io – build remarkable experiences at scale

Sanity is a customizable solution that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Categorized in