Discussion on how to automatically push references between document types in Sanity.io
8 replies
Last updated: Apr 9, 2020
Client insisting on an unwieldy content setup –You have two document types,
A) automatically push this reference, as described above
or...
B) the references to `artwork`s have to be setup in each Exhibition document anyway (you might only show 5 artworks from an artist’s entire catalogue). Is it possible to import references an array of document references from one document type –
Not essential, they can do manually – but it seems like this might be in reach?
Exhibitionand
Artist– once they’ve made an
Artwork, in which they define a reference to a specific
Artist, they would also like this to appear in an array of references in the
Artistdocument. I’m wondering if it’s possible to:
A) automatically push this reference, as described above
or...
B) the references to `artwork`s have to be setup in each Exhibition document anyway (you might only show 5 artworks from an artist’s entire catalogue). Is it possible to import references an array of document references from one document type –
exhibition– to another automatically?
Not essential, they can do manually – but it seems like this might be in reach?
Apr 8, 2020, 9:59 AM
NB: Why is this necessary? Why not show all artworks for a given artist on their page, and order by a given property – e.g.
artwork.date? Unfortunately they want very fine-grained control over which artworks are shown, and in what order. So an array of references absolutely seems like the best route, despite all the extra work involved. They will only have around 20 artists at any one time, with maybe max 60 artworks for each – so its a little crazy but not totally insane (I hope?).
Apr 8, 2020, 10:02 AM
Have you taken a look at custom workflows? https://www.sanity.io/docs/custom-workflows You can have a document action on an
artworkdocument called something like “Add to exhibition”, that handles adding it to an exhibition
Apr 8, 2020, 10:48 AM
Oh thanks so much
user H
– no I’d must’ve missed this being added, sorry! Looks very usefulApr 8, 2020, 1:23 PM
It’s brilliant, thank you
How can I check if that item already exists in the array? This is the final piece of the puzzle... I need to wrap this is an if statement, I just don’t know how to check if the item exists in the array on the document I want to insert it in?
Here’s my whole code:
user H
! All changing so fast. I’m nearly there! I’ve got a button which publishes an artwork, and in doing so inserts a reference in an array of references to
artworkson an artist document.
How can I check if that item already exists in the array? This is the final piece of the puzzle... I need to wrap this is an if statement, I just don’t know how to check if the item exists in the array on the document I want to insert it in?
patch.execute([{ "insert": { "before": "artworks[0]", "items": [{"_ref": <http://props.id|props.id>, "_type":"reference", "_key": <http://props.id|props.id> }] } }])
import { useState, useEffect } from 'react' import { useDocumentOperation } from '@sanity/react-hooks' export function setAndPublishAction(props) { if (props.type !== 'artwork') { return null } const { publish } = useDocumentOperation(<http://props.id|props.id>, props.type) const { patch } = useDocumentOperation(props.published.artist._ref, 'artist') 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…' : 'Amy, please don't press this one', onHandle: () => { // This will update the button text setIsPublishing(true) // Add artwork to "artworks" array on referenced Artist document patch.execute([{ "insert": { "before": "artworks[0]", "items": [{"_ref": <http://props.id|props.id>, "_type":"reference", "_key": <http://props.id|props.id> }] } }]) // Perform the publish publish.execute() // Signal that the action is completed props.onComplete() } } }
Apr 9, 2020, 12:24 AM
user H
thank you once again ! I thought I’d had a bit of a brainwave this morning – could possibly just check if the document has been published before...if (props.published) { return null }but this ended up being trickier than I expected;
I ended up doing what you suggested and trying a client fetch / patch within the studio (never done before!) and it worked great – so thank you
import CheckIcon from 'part:@sanity/base/check-icon' import { useState, useEffect } from 'react' import { useDocumentOperation } from '@sanity/react-hooks' import sanityClient from '@sanity/client' const client = sanityClient({ projectId: 'id', dataset: 'production', token: 'token', // or leave blank to be anonymous user useCdn: false }) import { nanoid } from 'nanoid' export function SetAndPublishAction(props) { const { publish } = useDocumentOperation(<http://props.id|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, icon: CheckIcon, label: isPublishing ? 'Publishing…' : 'Publish', onHandle: () => { // This will update the button text setIsPublishing(true) // Add artwork to "artworks" array on referenced Artist document if (props.type == 'artwork') { if (props.draft.artist._ref) { const artistId = props.draft.artist._ref const query = '*[_type == "artist" && _id == $artistId][0].artworks' const params = { artistId } client.fetch(query, params).then(artworks => { const check = artworks.some(artwork => artwork._ref === <http://props.id|props.id>) if (check) { console.log('Artwork already referenced on Artist'); } else { console.log('Artwork now added to Artist'); client .patch(artistId) // Ensure that the `artworks` arrays exists before attempting to add items to it .setIfMissing({artworks: []}) // Add the items after the last item in the array (append) .insert('before', 'artworks[0]', [ // Add a `_key` unique within the array to ensure it can be addressed uniquely // in a real-time collaboration context {_key: nanoid(), _ref: <http://props.id|props.id>, _type:"reference" } ]) .commit() } }) } else { alert('Please provide an artist reference.') } } // Perform the publish publish.execute() // Signal that the action is completed props.onComplete() } } }
Apr 9, 2020, 9:29 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.