How to add different views (Editor, Preview, JSON) to orderable-document-list?

13 replies
Last updated: Mar 4, 2023
Hi! I am using: https://github.com/sanity-io/orderable-document-list
Anyone knows how to add different views for the document? Eg. Editor, Preview, Json.
AI Update

Looking at the documentation, the orderable-document-list plugin creates a custom document list view, and to add different views (Editor, Preview, JSON) to the documents within it, you'll need to configure custom document views using the Structure Builder's defaultDocumentNode method.

Here's how to do it:

In your Structure Builder configuration (typically in sanity.config.ts or your structure file), you can use defaultDocumentNode to add multiple views to your documents. This works alongside the orderable-document-list plugin:

import { structureTool } from 'sanity/structure'
import { orderableDocumentListDeskItem } from '@sanity/orderable-document-list'

export default defineConfig({
  // ... other config
  plugins: [
    structureTool({
      structure: (S, context) => {
        return S.list()
          .title('Content')
          .items([
            // Your orderable document list
            orderableDocumentListDeskItem({
              type: 'yourDocumentType',
              S,
              context,
            }),
            // ... other items
          ])
      },
      // Add this to configure views for all documents
      defaultDocumentNode: (S, { schemaType }) => {
        // Apply custom views to specific document types
        if (schemaType === 'yourDocumentType') {
          return S.document().views([
            S.view.form(),  // Editor (default form view)
            S.view.component(YourPreviewComponent).title('Preview'),  // Custom preview
            S.view.component(JsonView).title('JSON'),  // JSON view
          ])
        }
        return S.document()
      }
    })
  ]
})

For the JSON view, you can create a simple component:

const JsonView = ({ document }) => {
  return (
    <pre style={{ padding: '1rem', overflow: 'auto' }}>
      {JSON.stringify(document.displayed, null, 2)}
    </pre>
  )
}

The key insight from the Structure Builder documentation and the Component View feature is that defaultDocumentNode applies to all document editors in your Studio, including those opened from the orderable-document-list. This means your custom views will be available when you click into any document from your orderable list.

Each view you add will appear as a tab at the top of the document editor, allowing users to switch between the Form (editor), your custom Preview, and JSON views.

Note: As mentioned in this community discussion, if the standard defaultDocumentNode approach doesn't work with your specific plugin configuration, you can also pass a child configuration directly to the orderable document list item that specifies the views, though the defaultDocumentNode approach is the recommended pattern for Studio v3.

Show original thread
13 replies
You could use this to add a custom view.
You mean this?
export const getDefaultDocumentNode = ({documentId, schemaType}) => {
  // Render the JSON preview only on posts or the siteSettings document
  if (schemaType === "post" || documentId === "siteSettings") {
    return S.document().views([
      S.view.form(),
      S.view.component(JsonPreview).title('JSON')
    ])
  }
}
Didnt work for the plugin i am using. But i fixed the problem by adjusting the plugin:
https://www.sanity.io/plugins/orderable-document-list

Called function from desk structure.
export function orderableDocumentListDeskItem(config: OrderableListConfig, views) {



return S.listItem()

.title(listTitle)

.id(listId)

.icon(listIcon)

.child(

Object.assign(S.documentTypeList(type).serialize(), {

// Prevents the component from re-rendering when switching documents

__preserveInstance: true,

// Prevents the component from NOT re-rendering when switching listItems

key: listId,


type: 'component',

component: OrderableDocumentList,

options: { type, filter, params, client },

I added this. Where i pass in the views i want to the plugin
child: (documentId: any) =>

S.document()

.documentId(documentId)

.schemaType(type)

.views(views(S)),


menuItems: [

S.menuItem()
`.title(
Create new ${typeTitle}
)`
.intent({ type: 'create', params: { type } })

.serialize(),
`S.menuItem().title(
Reset Order 2
).icon(GenerateIcon).action(
resetOrder
).serialize(),` `S.menuItem().title(
Show Increments
).icon(SortIcon).action(
showIncrements
).serialize(),

        
],

      
})`
)

.serialize()
Glad you figured it out! 😊
Thanks for the help thou:)
It worked straight with mine, although I think my configuration is pretty much simpler than yours. I just did a quick try.
But the good thing is I learned from your example that you could filter it out to show only on specific schema. That was some question I had before I saw your example.
hmm. Maybe i made a mistake in the default document node.
Ah, yes, I remember, I had to move out the
JSONViewer
component because it can’t seem to compile. I had to create a
.tsx
file for that component
Yea sure!I like to do everything in the structure to get full control so i add view like this:


.child(

S.editor()

.schemaType('aboutPage')

.documentId('aboutPage')

.views(Views(S))
Yea all components used in views has to be a react component.
Right. I’m with you in doing it in desk structure. 😉
Checked out your website. Very cool! And thanks for teaching webdev to others 🙂
thank you
user J
. it means a lot. 😊

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?