Discussion on displaying file URLs for a custom component in a Sanity.io project
8 replies
Last updated: Aug 22, 2021
P
Hi, I have written a custom component to display a file url below the file upload field. So far, it correctly displays the url, but only for the first element of the array (works if I reorder the elements as well). How could I make sure I get the correct values for each element of the array? (Code and screenshots are attached below)
Aug 21, 2021, 11:44 AM
P
FontUrl.js component code:
import React from 'react' import { withDocument } from 'part:@sanity/form-builder' // build a file url export function fileUrl(reference) { const project = { projectId: process.env.SANITY_STUDIO_API_PROJECT_ID, dataset: process.env.SANITY_STUDIO_API_DATASET || 'production' } const referenceArray = reference.split('-') const asset = { assetId: referenceArray[1], extension: referenceArray[2] } return `<https://cdn.sanity.io/files/${project.projectId}/${project.dataset}/${asset.assetId}.${asset.extension}>` } const FontUrl = React.forwardRef((props) => { for(let i=0; i<props.document.fontFiles.length; i++) { const reference = props.document.fontFiles[i].asset._ref return ( <p>{fileUrl(reference)}</p> ) } }) export default withDocument(FontUrl)
Aug 21, 2021, 11:47 AM
P
A snippet of the schema code:
{ name: 'fontFiles', title: 'Font files', description: 'Upload font files, add below with @font-face. Accepted formats: .woff, .woff2', type: 'array', of: [ { type: 'file', options: { accept: '.woff2, .woff', }, fields: [{ name: 'fontUrl', title: 'Font URL', description: 'Use in CSS @font-face', type: 'url', // below adding a component inputComponent: FontUrl, readOnly: true, options: { isHighlighted: true, } }], } ] },
Aug 21, 2021, 11:50 AM
P
Screenshots (sorry, components as well as other details are not finished yet)
Aug 21, 2021, 11:59 AM
D
Hi Paul, do you want
You could do something like this:
<FontUrl>to display the urls of all uploaded fonts? If so, you should change the code so FontUrl doesn’t return from within a loop (will only loop once).
You could do something like this:
const FontUrl = React.forwardRef((props) => { const { fontFiles } = props.document return ( <> <p>{fontFiles.map(fontFile => fileUrl(fontFile.asset._ref)})}</p> </> ) })
Aug 21, 2021, 3:40 PM
P
It's slightly different. I wanted to display only the url for the selected/expanded field. You can see on the screenshots that currently it displays the the url of the first font (.woff2) in both cases. I wonder if it would be possible to display .woff2 for the first one and .woff for the second one (with other data being different as well, of course)
Aug 21, 2021, 4:12 PM
D
In that case you’ll need to import
withValuePathas well, as well, it will show you which array the current custom field belongs to, so you can get the file.
import { withDocument, withValuePath } from 'part:@sanity/form-builder' export const FontUrl = withValuePath(withDocument(({ document, getValuePath }) => { console.log(document) // { _id: ... } console.log(getValuePath()) // ["content", { _key: ... }] }))
Aug 21, 2021, 4:39 PM
P
Finally finished it! I think it turned out quite nice.
Thank you so much for helping me out!
const FontUrl = React.forwardRef((props, ref) => { const matchingUrl = props.document.fontFiles.find(fontFile => fontFile._key === props.getValuePath()[1]._key); return ( <p>{matchingUrl.asset ? fileUrl(matchingUrl.asset._ref) : null}</p> ) }) export default withValuePath(withDocument(FontUrl))
Aug 22, 2021, 5:35 AM
D
Congrats Paul! If you'd like to style the url to look the same as other fields in the studio, check out sanity ui! https://www.sanity.io/ui/docs
Aug 22, 2021, 5:39 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.