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.

Virtual fields set by BeforeReadCollectionHook return data unflattened (always in all locales)

default discord avatar
_j3ns_last year
6

I have a [virtual](

https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges

) path, breadcrumbs and alternatePaths field on my collection items.



Since now, I used field afterRead hooks to generate the breadcrumbs based on the items parent page and the path and alternatePaths based on the breadcrumbs. This worked fine.



To improve the performance (only recursively iterate over the parents once instead of for each of the hook), I now want to use a BeforeReadCollection hook to get the data for the virtual fields. I do this as follows:



const setVirtualFieldsHook: CollectionBeforeReadHook = async ({ doc, req, collection }) => {
    const breadcrumbs = await getBreadcrumbsForAllLocales({
      req,
      collection,
      parentField,
      parentCollection,
      data: doc,
    })

    const paths = {
      de: pathFromBreadcrumbs({ locale: 'de', breadcrumbs: breadcrumbs.de }),
      en: pathFromBreadcrumbs({ locale: 'en', breadcrumbs: breadcrumbs.en }),
    }

    const alternatePaths = {
      de: paths.de,
      en: paths.en,
    }

    if (req.locale === 'all') {
      return {
        ...doc,
        path: paths,
        breadcrumbs,
        meta: {
          ...doc.meta,
          alternatePaths,
        },
      }
    } else {
      return {
        ...doc,
        path: paths[req.locale as 'de' | 'en'],
        breadcrumbs: breadcrumbs[req.locale as 'de' | 'en'],
        meta: {
          ...doc.meta,
          alternatePaths,
        },
      }
    }
  }


export const Pages: CollectionConfig = {
   ....
   hooks: {
           beforeRead: [setVirtualFieldsHook],
    },
   fields: [
      path: { type: text, ... },
      breadcrumbs: { type: 'array', ...}
      meta: { type: group, ..., fields: { name: 'alternatePaths', type: 'array', ... }},
    ]
    ....
}


The issue I have, is that the localized path and breadcrumb fields are not flattened.



(My comment below contains an example result from the REST API)



For example, this query:



/api/pages/62d52d26a495feed7b990b40?locale=de

Returns the following unflattened data:




{
  ...
  "breadcrumbs": {
    "de": [
      {
        "slug": "galerie",
        "path": "/de/galerie",
        "label": "Galerie"
      },
      {
        "slug": "glamping-galerie",
        "path": "/de/galerie/glamping-galerie",
        "label": "Glamping Galerie"
      }
      ],
    "en": [
      {
        "slug": "gallery",
        "path": "/en/gallery",
        "label": "Gallery"
      },
      {
        "slug": "glamping-gallery",
        "path": "/en/gallery/glamping-gallery",
        "label": "Glamping Gallery"
      }
    ]
  },
}


I added a logging statement to the end of the hook, and the hook respects the locale and returns the data correctly. I guess the problem is somewhere else.



Am I doing something wrong, or is this an issue with Payload?



Virtual fields set by BeforeReadCollectionHook return data unflattened (always in all locales)

  • default discord avatar
    notchrlast year

    I'm having a hard time understanding the issue



    But I'm happy to help, can you clarify it a bit more?, sorry!

  • default discord avatar
    _j3ns_last year

    Hey

    @486710146651652106

    👋


    The issue is that when fetching a page from the API or in the Adminpanel for a specific locale (e.g. for german) the field data for all locales are returned (as seen in the json snippet above). This is the case even though the CollectionBeforeReadHook respects the locale and returns the correct data.

  • default discord avatar
    notchrlast year
  • default discord avatar
    _j3ns_last year

    Yes, you can see the REST URL with the locale in the message above

  • default discord avatar
    notchrlast year

    Are you concerned that it's just passing extra information?

  • default discord avatar
    _j3ns_last year

    The problem is that the Admin panel also receives an object containing all locales for the path field instead of just the path for the requested locale.



    This means that instead of the path text field displaying "/en/mypath" it contains "[Object object].



    I do not understand why this happens because the hook I created looks alright.



    I found the issue, inside the getBreadcrumbsForAllLocales I have a function which recursivly iterates over all parents of a page. In there I fetched the parent as follows:



    retrievedParent = await req.payload.findByID({
            id: parent,
            collection: collection,
            depth: 0,
            disableErrors: true,
            locale: locale,
            req: req,
          })


    When removing the

    req: req

    (so that the req is not passed), everything works again. Passing the req in there causes problems with the localization.

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.