Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

Mime Type For Admin Condition Across Relations

default discord avatar
grant_msft3 years ago
8

Currently I have a Media collection that can accept upload.mimeTypes: ['image/

', 'video/

']



I have an Article collection that has a relationship to media. In the article collection I want to conditionally display fields using admin.condition based on if the mime type of the Media doc that is selected.



Is this possible? The selected media's data is the media _id instead of the media doc as a whole. Is there a place I should write an api query to power admin.conditions for the fields i want to conditionally show on Articles?

  • discord user avatar
    jacobsfletch
    3 years ago
    @1054487065674403972

    yep I completely understand what your describing here, your media field is a relationship to an upload, which is just a reference to an id and not the full doc. What you need to do is fetch the full doc—but you should not make

    admin.condition

    async because this function is run very frequently and this would not be performant. Instead, use another field named

    mimeType

    or similar, then in an

    afterChange

    hook on your collection, fetch the full doc and save its mime-type to that field. This way it only makes the request once when the document is created or updated, and that data is now passed through to your condition as expected. What do you think?

  • default discord avatar
    grant_msft3 years ago

    Awesome, this makes sense and I have tried this approach before posting here.



    Do you have any examples of this flow?



    I've tried what you described but I'm having trouble getting the afterChange hook to fire (I'm assuming I would see logs from it in my browser console when fired). Here is a snippet of my collection.



    const afterMediaChange: FieldHook = (args) => {
        console.log('afterMediaChange', args);
        return '';
    };
    
    const articles: CollectionConfig = {
        slug: 'articles',
        fields: [
            // ....
            {
                name: 'heromedia',
                label: 'Hero Media',
                type: 'relationship',
                relationTo: 'media',
                hasMany: false,
                hooks: {
                    afterChange: [afterMediaChange],
                },
            },
        ]
    }


    Must I fully type the generics in FieldHook for this to work?

  • discord user avatar
    jacobsfletch
    3 years ago

    Hmm this looks correct to me. Are you saving the document to trigger the hook? Fully typing the field hook wouldn't change anything here. Did your server restart after making this change? Try to throw a collection-level hook in here and see if that fires.

  • default discord avatar
    grant_msft3 years ago

    Oh its on save? I thought it was when selecting a new doc from the relationship. I've just been changing the value and I haven't been saving.

  • discord user avatar
    jacobsfletch
    3 years ago

    Yep 👍 and that's deliberate to avoid making many network requests



    beforeChange

    would work better here, too

  • default discord avatar
    grant_msft3 years ago

    Got it. That adds a step for the use case in this flow. I might take a different approach then. Thanks for the info and help!

  • discord user avatar
    jacobsfletch
    3 years ago

    You could alternatively use a custom component that watches that field, makes the request on every change, and returns the mime-type



    In your custom component you'd fire the

    useFormFields

    hook to subscribe to the relationship, then use that value as a dependency of a

    useEffect

    that makes the request, something like this (not tested):



      ...
      const [mimeType, setMimeType] = useState<string>();
      const { value: mediaID } = useFormFields(([fields, dispatch]) => fields.media);
    
      useEffect(() => {
        const makeReq = async () => {
          const req = await fetch(`${YOUR_SERVER_URL}/media/${mediaID}`)
          const json = await req.json();
          if (json.mimeType) {
            setMimeType(json.mimeType)
          }
        }
      }, [mediaID]);
    
      if (mimeType.startsWith('image/')) {
        return (
          ...
        )
      }
      
      return null;
  • default discord avatar
    grant_msft3 years ago

    ah i see, that makes sense too.

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get dedicated engineering support directly from the Payload team.