sanity icon indicating copy to clipboard operation
sanity copied to clipboard

How do I get the index or nth value of a specific block type within the portable text types in SanityContent?

Open toddpadwick opened this issue 2 years ago • 1 comments

Because this plugin renders Sanity blocks without exposing a for loop, I am wondering how I can access or pass the blocks index and nth increment number to each component.

I need to be able to determine the index of a specific block in my portable text and pass this value into the component. Can anyone tell me how this might be possible?

<template>
  <div class="body-content">
    <SanityContent :blocks="content" :serializers="serializers" :renderContainerOnSingleChild="'section'"/>
  </div>
</template>


<script setup>
  import AnnotatedVisual from '~/components/block/section/AnnotatedVisual.vue';
  import Gallery from '~/components/block/section/Gallery.vue';
  import Testimonial from '~/components/block/section/Testimonial.vue';
  import Videos from '~/components/block/section/Videos.vue';
  import TextOverVisual from '~/components/block/section/TextOverVisual.vue';
  import Link from '~/components/Link.vue';
  // import Block from '~/components/block/section/Block.vue';
  import Subscribe from '~/components/block/section/Subscribe.vue';
  import Articles from '~/components/block/section/Articles.vue';
  import CaseStudies from '~/components/block/section/CaseStudies.vue';
  import Excerpts from '~/components/block/section/Excerpts.vue';

  const props = defineProps({
    content:{required:true,type:Array}
  })

  const serializers = {
    container: 'section',
    types: {
      gallery:Gallery,
      annotatedVisual:AnnotatedVisual, // the component I need to get the index for
      testimonial:Testimonial,
      videos:Videos,
      textOverVisual:TextOverVisual,
      articles:Articles,
      caseStudies:CaseStudies,
      subscribe:Subscribe,
      excerpts:Excerpts
      // block:Block
    },
    marks: {
      link: Link,
    },
  }
</script>



toddpadwick avatar Nov 13 '23 12:11 toddpadwick

Hey @toddpadwick I actually had a chat with someone about this in the Nuxt Sanity Slack channel last month.. Basically I ran into this issue about a year ago and ever since I just found it much easier to have my sanity-content (rich-text) remain a pretty simple text module within my page-builders. Many devs try to extend the SanityContent to include many types of dynamic blocks and it leads to problems like this. Keep it simple, maybe with just text/link serializers and a basic image block (or whatever you think is necessary for your project).

In your page sections/modules you can use v-if or component :is:

<script setup>
// Props
const props = defineProps({
  sections: {
    type: Array
  }
})

// Sections
const chooseSection = (section) => {
  if (section._type === 'firstSection') return resolveComponent('first-section')
  if (section._type === 'secondSection') return resolveComponent('second-section')
  if (section._type === 'richText') return resolveComponent('rich-text')
}
</script>

<template>
  <component
    :is="chooseSection(section)"
    v-for="section in props.sections"
    :key="section._key"
    :section="section"
  />
</template>

Here is the link to our convo: https://sanity-io-land.slack.com/archives/CK0G59KB3/p1697471562817659

rylanharper avatar Nov 15 '23 19:11 rylanharper