
Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag storeYou're on the right track! Document actions aren't the best fit for this use case since they're designed for document-level operations in a dropdown menu. What you actually want is a custom input component with a button right next to the field, similar to how the slug generator works.
The Form Components API is exactly what you need. You can create a custom input component that includes a button positioned near your field to trigger the API call and populate other fields.
Here's a practical example of how to implement this:
import { StringInputProps, set, useFormValue } from 'sanity'
import { Button, Stack, TextInput } from '@sanity/ui'
import { useState } from 'react'
export function ItemNumberInput(props: StringInputProps) {
const { onChange, value, elementProps } = props
const [loading, setLoading] = useState(false)
const handleFetch = async () => {
if (!value) return
setLoading(true)
try {
const response = await fetch(`https://your-api.com/items/${value}`)
const data = await response.json()
// Populate multiple fields using onChange with paths
onChange([
set(value), // Keep current field value
set(data.title, ['title']), // Populate title field
set(data.description, ['description']), // Populate description
set(data.category, ['category']), // Add more fields as needed
])
} catch (error) {
console.error('Failed to fetch item data:', error)
} finally {
setLoading(false)
}
}
return (
<Stack space={3}>
<TextInput
{...elementProps}
value={value || ''}
onChange={(event) => onChange(set(event.currentTarget.value))}
/>
<Button
text="Fetch Item Details"
onClick={handleFetch}
disabled={!value || loading}
tone="primary"
/>
</Stack>
)
}Then in your schema:
defineField({
name: 'itemNumber',
type: 'string',
title: 'Item Number',
components: {
input: ItemNumberInput
}
})Key advantages of this approach:
useFormValue() if neededFor more sophisticated implementations, check out these guides:
If you need to populate fields conditionally only if they're empty, you can use setIfMissing instead of set:
import { setIfMissing } from 'sanity'
onChange([
set(value),
setIfMissing(data.title, ['title']), // Only set if title is empty
])You can also access the entire document context if you need to make decisions based on other field values:
const document = useFormValue([]) as anyThis approach gives you much more control than document actions and creates exactly the UX pattern you're looking for - a button-triggered action right next to the field where editors are working!
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.
Content operations
Content backend


The only platform powering content operations
By Industry


Tecovas strengthens their customer connections
Build and Share

Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag store