Troubleshooting custom validation for image dimensions in a Sanity schema

31 replies
Last updated: Dec 22, 2022
Quick question. Is there a way to log a value in a sanity document?
Dec 22, 2022, 7:55 PM
Hey
user J
! Can you provide some more context around what you're trying to do? Is this in a custom component or inside of a regular schema?
Dec 22, 2022, 7:58 PM
Im trying to create custom validation where an image dimensions conforms to a minimum ratio of width/length in my schema
Dec 22, 2022, 7:59 PM
const minHeight = dimensions.width * 5 / 4
Dec 22, 2022, 8:00 PM
so i would like to console.log minHeight
Dec 22, 2022, 8:00 PM
to be clear my dimension validation is otherwise working correctly
Dec 22, 2022, 8:00 PM
Is min height defined in your schema files or a value you've entered into a field?
Dec 22, 2022, 8:02 PM
validation: Rule => Rule.custom(image => {

if (!image) return true

const { dimensions } = decodeAssetId(image.asset._ref)

const minHeight = dimensions.width * 5 / 4

return dimensions.width >= 1000 && dimensions.height >= minHeight || "Minimum width is 1000. Image must be rectangle."

}),
Dec 22, 2022, 8:03 PM
its placed within my custom validation
Dec 22, 2022, 8:03 PM
so its in my field
Dec 22, 2022, 8:04 PM
That's just works like a normal function, so you should be able to do this:
validation: Rule => Rule.custom(image => {
        if (!image) return true
        const { dimensions } = decodeAssetId(image.asset._ref)
        const minHeight = dimensions.width * 5 / 4
        console.log(minHeight)
        return dimensions.width >= 1000 && dimensions.height >= minHeight || "Minimum width is 1000. Image must be rectangle."
      }),
Dec 22, 2022, 8:07 PM
Thats what i thought but its not appearing in console. When does the function run?
Dec 22, 2022, 8:09 PM
In a string field, it runs on each key stroke but I'm not 100% sure for an image field. It most likely runs when the component mounts and when the value is changed.
Dec 22, 2022, 8:11 PM
Yes that would make sense since thats when an error appears. But still no console log appearing.
Dec 22, 2022, 8:12 PM
I confirmed it runs on mount and when it changes with a similar function:
validation: Rule =>
        Rule.custom(async image => {
          if (!image) return true;
          const dimensions = await client.fetch(
            `*[_id == "${image.asset._ref}"].metadata.dimensions[0]`
          );

          const minHeight = (dimensions.width * 5) / 4;
          console.log('MINHEIGHT', minHeight);
          return (
            (dimensions.width >= 1000 && dimensions.height >= minHeight) ||
            'Minimum width is 1000. Image must be rectangle.'
          );
        }),
If you're not getting a console log, there's likely an error in your function. Is there a warning next to your schema title? What is your
decodeAssetId
function doing?
Dec 22, 2022, 8:21 PM
Very strange. I am getting no warning. I tried copying and pasting your code and getting the same results...
Dec 22, 2022, 8:27 PM
const pattern = /^image-([a-f\d]+)-(\d+x\d+)-(\w+)$/


const decodeAssetId = id => {

const [, assetId, dimensions, format] = pattern.exec(id)

const [width, height] = dimensions.split("x").map(v => parseInt(v, 10))


return {

assetId,

dimensions: { width, height },

format,

}

}
Dec 22, 2022, 8:28 PM
{

name: "image",

title: "Featured Image",

type: "image",

options: {

accept: "image/*",

},

validation: Rule => Rule.custom(image => {

if (!image) return true

const { dimensions } = decodeAssetId(image.asset._ref)

const minHeight = dimensions.width * 5 / 4

return dimensions.width >= 1000 && dimensions.height >= minHeight || "Minimum width is 1000. Image must be rectangle."

}),

validation: Rule => Rule.required(),

},
Dec 22, 2022, 8:28 PM
Can you share the schema you've added this to? It might not be in the right place.
Dec 22, 2022, 8:28 PM
thats the whole field
Dec 22, 2022, 8:28 PM
export default {

name: "collection",

title: "Collections",

type: "document",

fields: [

{

name: "title",

title: "Title",

type: "string",

},

{

name: "slug",

title: "Slug",

type: "slug",

options: {

source: "title",

maxLength: 96,

},

},

{

name: "image",

title: "Featured Image",

type: "image",

options: {

accept: "image/*",

},

validation: Rule => Rule.custom(image => {

if (!image) return true

const { dimensions } = decodeAssetId(image.asset._ref)

const minHeight = dimensions.width * 5 / 4

return dimensions.width >= 1000 && dimensions.height >= minHeight || "Minimum width is 1000. Image must be rectangle."

}),

validation: Rule => Rule.required(),

},

{

name: "description",

title: "Description",

type: "text",

},

{

name: "subcategories",

title: "Subcategories",

type: "array",

of: [

{

type: "reference",

to: [{ type: "collection" }],

},

],

},

],


};


const pattern = /^image-([a-f\d]+)-(\d+x\d+)-(\w+)$/


const decodeAssetId = id => {

const [, assetId, dimensions, format] = pattern.exec(id)

const [width, height] = dimensions.split("x").map(v => parseInt(v, 10))


return {

assetId,

dimensions: { width, height },

format,

}

}
Dec 22, 2022, 8:29 PM
Ok, this is logging for me using that function:
{
      name: 'image',
      type: 'image',
      validation: Rule =>
        Rule.custom(image => {
          if (!image) return true;
          const dimensions = decodeAssetId(image.asset._ref).dimensions;

          const minHeight = (dimensions.width * 5) / 4;
          console.log('MINHEIGHT', minHeight);
          return (
            (dimensions.width >= 1000 && dimensions.height >= minHeight) ||
            'Minimum width is 1000. Image must be rectangle.'
          );
        }),
    },
I think the issue is that you're redefining your
validation
by adding
validation: Rule => Rule.required()
. You should remove that and capture it in your custom rule instead:
{
      name: 'image',
      type: 'image',
      validation: Rule =>
        Rule.custom(image => {
          if (!image) return 'An image is required';
          const dimensions = decodeAssetId(image.asset._ref).dimensions;

          const minHeight = (dimensions.width * 5) / 4;
          console.log('MINHEIGHT', minHeight);
          return (
            (dimensions.width >= 1000 && dimensions.height >= minHeight) ||
            'Minimum width is 1000. Image must be rectangle.'
          );
        }),
    },
Dec 22, 2022, 8:35 PM
Still no log 😞 its strange because I am using this exact same validation sans minHeight in another schema and it is working correctly even with the second validation with Rule.required(). I wanted to log minHeight because I was adding images with equal height/width and getting no errors. Now I am confused on two fronts because I cant log the variable. I wonder if it could have something to do with using the documentsPane plugin and my deskStructure?? I really have no idea what the issue is.
Dec 22, 2022, 8:47 PM
wait never mind lol
Dec 22, 2022, 8:52 PM
I was positive that I had restarted the studio in my console a few times and this had not worked I did it one more time and the log is appearing
Dec 22, 2022, 8:53 PM
validation appears to be working as well
Dec 22, 2022, 8:53 PM
Awesome!
Dec 22, 2022, 8:53 PM
thank you so much 😭
Dec 22, 2022, 8:54 PM
You're welcome!
Dec 22, 2022, 8:55 PM
In case you are interested I think you are spot on with redefining my validation. The reason why it was working in my other schema is that I have
validation: Rule => Rule.required()
applied to an array of images with their own custom validation inside. So I think it was working properly in that field because the validation is occurring at different levels.
Dec 22, 2022, 8:59 PM
Ah, thanks for clearing that up!
Dec 22, 2022, 9:11 PM

Sanity– build remarkable experiences at scale

The Sanity Composable Content Cloud is the 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?