✨Discover storytelling in the AI age with Pixar's Matthew Luhn at Sanity Connect, May 8th—register now

Returning a specific number of items with `S.documentTypeList()` in Sanity.io

10 replies
Last updated: Dec 9, 2021
Hello! Is it possible to return a specific number of items, rather than all of them, for
S.documentTypeList()
using the desk structure builder? Its
.filter
expects a GROQ query string, but it isn’t itself a GROQ query so adding
[0…19]
doesn’t work 😢 Any other ways around this? Is there a way to access the index and pass that to
.params
for use in
.filter
?
Dec 7, 2021, 12:38 AM
I found a previous example using
rxjs
that may work for you:
// deskStructure.js
import React from 'react'
import S from '@sanity/base/structure-builder'
import documentStore from 'part:@sanity/base/datastore/document'
import {map} from 'rxjs/operators'
...
const query = `*[_type == 'room'][0...19]`

export default S.listItem()
  .title('Recently Published Rooms')
  .child(() =>
    documentStore.listenQuery(query).pipe(
      map(rooms =>
        S.list()
          .title('Rooms')
          .items([
            ...rooms.map(room =>
              S.listItem()
                .title(room.title)
            )
          ])
       )
     )
   )
Hope that helps!
Dec 7, 2021, 1:35 AM
Thanks!
Dec 7, 2021, 1:53 AM
Alternatively, I've worked out the following that does not require `rxjs`:
import client from 'part:@sanity/base/client'
import S from '@sanity/desk-tool/structure-builder'

const sanityClient = client.withConfig({apiVersion: '2021-03-25'})

const query = `*[_type == 'room']| order(_updatedAt desc)[0...19]`

export default S.listItem()
  .title('Recently Published Rooms')
  .child(async () => {
    const rooms = await sanityClient.fetch(query)

    return S.list()
      .title('Recently Published Rooms')
      .items([
        ...rooms.map(room => S.listItem()
          .id(room._id)
          .title(room.title)
          .child(
            S.document()
            .id(room._id)
          )
        )
      ])
    })
Dec 7, 2021, 3:46 AM
Alternatively, I've worked out the following that does not require `rxjs`:
import client from 'part:@sanity/base/client'
import S from '@sanity/desk-tool/structure-builder'

const sanityClient = client.withConfig({apiVersion: '2021-03-25'})

const query = `*[_type == 'room']| order(_updatedAt desc)[0...19]`

export default S.listItem()
  .title('Recently Published Rooms')
  .child(async () => {
    const rooms = await sanityClient.fetch(query)

    return S.list()
      .title('Recently Published Rooms')
      .items([
        ...rooms.map(room => S.listItem()
          .id(room._id)
          .title(room.title)
          .child(
            S.document()
            .id(room._id)
          )
        )
      ])
    })
Dec 7, 2021, 3:46 AM
Oh that looks great, thank you
user M
Dec 7, 2021, 7:03 PM
Oh that looks great, thank you
user M
Dec 7, 2021, 7:03 PM
While the snippet without rxjs works well for static lists it won’t receive updated content. So changing the title of a document won’t be visible in the list. I think both of the snippets will show both drafts and published items in the same lists.
Dec 8, 2021, 6:50 AM
I resolved the draft/published items issue by adding
&& !(_id in path("drafts.**"))
to the query,
(update: that only shows the published doc) but you’re right
user B
, I’m not able to update the title shown in the list when I update the document. Is there a way to do it without rxjs? I’d prefer not to add a new library just for this.
Dec 8, 2021, 6:23 PM
I believe you need to use the
documentStore.listenQuery(query).pipe(...)
bit if you want updates without rerendering the pane.
Dec 8, 2021, 6:25 PM
Updating what ended up working for me, in case anyone is looking for a similar solution:
const newRoomsQuery = `*[_type == 'room' && !(_id in path("drafts.**"))]| order(date desc)[0..19]`

const newRooms = await sanityClient.fetch(newRoomsQuery)

.items([
  S.listItem({
    id: 'newest-rooms',
    title: 'New',
    icon: MdNewReleases,
    child: () =>
      S.list()
        .title('New Rooms')
        .items([
          ...newRooms?.map(room =>
            S.documentListItem().id(room._id).schemaType('room')
          )
        ])
  }),
  // ...
])
Dec 9, 2021, 12:59 AM

Sanity– build remarkable experiences at scale

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

Was this answer helpful?