Accessing document values in custom document actions and displaying custom error messages

12 replies
Last updated: Mar 14, 2021
Hey, can I access the document values in custom document actions? Like if want to create a custom "Publish" button where I want to access some of the documents values?
Mar 11, 2021, 7:27 PM
I just recently implemented document actions to set a readOnly hidden field of type
slug
with values from within the document including a field from a referenced document.
Mar 11, 2021, 7:44 PM
Here is my action, named `SetSlugAndPublishAction`:

// setSlugAndPublishAction.js

import {useState, useEffect} from 'react'
import {useDocumentOperation} from '@sanity/react-hooks'
import sanityClient from '@sanity/client'

const sanityClientConfig = {
  projectId: process.env.SANITY_STUDIO_API_PROJECT_ID,
  dataset: process.env.SANITY_STUDIO_API_DATASET,
  token: process.env.SANITY_STUDIO_API_TOKEN,
  useCdn: true,
}

export default function SetSlugAndPublishAction(props) {
  const {patch, publish} = useDocumentOperation(props.id, props.type)
  const [isPublishing, setIsPublishing] = useState(false)
  
  useEffect(() => {
    // if the isPublishing state was set to true and the draft has changed
    // to become `null` the document has been published
    if (isPublishing && !props.draft) {
      setIsPublishing(false)
    }
  }, [props.draft])
  
  return {
    disabled: publish.disabled,
    label: isPublishing ? 'Publishing…' : 'Publish',
    onHandle: async () => {
      // This will update the button text 
      setIsPublishing(true)

      const client = sanityClient(sanityClientConfig)
      let slug = '', name = props.draft.name
      
      /// TODO: load a slugify function from the document for this task
      switch (props.type) {
        case 'tag':
          let gameName = props.draft.game._ref
          const query = '*[_type == "game" && _id == $gameID][0] {name}'
          const params = {gameID: gameName}

          await client.fetch(query, params).then(game => {
            gameName = !!game ? game.name : gameName
          })

          name = slug = `${gameName}-tag-${props.draft.tagnumber}`
          break;
        default:
          break;
      }

      // Set the slug
      patch.execute([{set: { slug: { _type: 'slug', current: slug.toLowerCase() }, name: name.toLowerCase() }}])
      
      // Perform the publish
      publish.execute()
      
      // Signal that the action is completed
      props.onComplete() 
    }
  }
}
Mar 11, 2021, 7:46 PM
Nice! Thanks for the example
Mar 11, 2021, 9:32 PM
user Q
you should add that as a sanity snippet on the community pages. Someone shared my pseudo gist code the other day too.
Mar 12, 2021, 6:48 AM
user L
this was definitely a collaboration between the both of us. I will look into creating my first snippet and give you credit where I can.
Mar 12, 2021, 4:05 PM
Do you know if there is a way to display a custom error message from a custom action? I want to do an API call before publish and if it fails I want to display some sort an error message to the user
Mar 14, 2021, 8:50 PM
user E
I am doing exactly that with a toast.
Mar 14, 2021, 8:50 PM
Mar 14, 2021, 8:51 PM
Actually wrong one. This is the toast info https://www.sanity.io/ui/docs/component/toast
Mar 14, 2021, 8:53 PM
Ooo nice! Thanks
Mar 14, 2021, 8:53 PM
import {useToast} from '@sanity/ui'
...

const toast = useToast()
...

toast.push({status:'error', title: error})

Mar 14, 2021, 8:55 PM

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?