can i load dynamic data to an options field?
the code below doesn't work but i would like to loop on a collection and gets its internal values like this:
fields: [
{
name: 'Facets',
type: 'select',
hasMany: true,
options: [
async () => {
const facets = await payload.find({
collection: "facet",
})
let facet_values = facets.map(function (facet) {
return facet.values;
});
let brands_and_categories = facet_values.map(function (v) {
return {
value: v.name
key, v.id
};
});
return brands_and_categories;
}
],
]}
``
also note that i tried also to set relationship but then couldnt get the values of the 'facets' collection in the select box:
// {
// name: 'Facets',
// type: 'relationship',
// hasMany: true,
// relationTo: 'facets',
// },
```
Hey @megetron - I would revert back to your relationship field and populate the values using a field hook like this:
const getFacets: FieldHook = async () => {
const facets = await payload.find({
collection: 'facets',
});
if (facets.docs) {
return facets.docs.map((doc) => doc.id);
} return null;
};
{
name: 'Facets',
type: 'relationship',
relationTo: 'facets',
hasMany: true,
hooks: {
afterRead: [getFacets],
},
},
thank you.
i have reedited the function to retrieve the internal values of the facets collection:
const getFacets: FieldHook = async () => {
const facets = await payload.find({
collection: 'facets',
});
if (facets.docs) {
let values = facets.docs.map(obj => obj.values).flat();
console.log(values)
// return ['samsung', 'google'] // this wont work as well
return values
}
return null;
};
// console.log output
// [
// { name: 'Google', code: 'google', id: '642d55dea5fdab6fb3d3fe02' },
// { name: 'Samsung', code: 'samsung', id: '642d55eca5fdab6fb373de08' },
// ]
where the output would be expected to be override the data in the select box.
@megetron return only the id, this will pull in the full doc for you.
it doesn't work as well, maybe because the id is not the id of the document, rather its the id of the internal 'values' key inside the facets document?
maybe i will share the whole code, hopefully it will explain better than i did:
// blocks/filter-by-facets.ts
import { Block , FieldHook} from 'payload/types';
import payload from 'payload';
const getFacets: FieldHook = async () => {
const facets = await payload.find({
collection: 'facets',
});
if (facets.docs) {
const ids = facets.docs.map(obj => obj.values.map(val => val.id)).flat();
console.log(ids)
//return '642d55dea5fdab6fb3d3fe02' // didnt work
return ids
}
return null;
};
export const FilterFacetsBlock: Block = {
slug: 'FilterFacets',
fields: [
{
name: 'Facets',
type: 'relationship',
relationTo: 'facets',
hasMany: true,
hooks: {
afterRead: [getFacets],
},
},
{
name: 'ContainsAny',
type: 'checkbox',
},
]
};
// collections/collections.ts
import { CollectionConfig } from 'payload/types';
import { FilterFacetsBlock } from '../blocks/filter-by-facets';
const Collections: CollectionConfig = {
slug: 'collections',
fields: [
{
name: 'productVariants',
type: 'blocks',
blocks: [
FilterFacetsBlock, // here i would like the productVariants to be populated from the 'values' array inside the facet doc
]
},
],
}
export default Collections;
// facets collections
const facets: CollectionConfig = {
slug: 'facets',
fields: [
{
name: 'values',
type: 'array',
fields: [
{
name: 'name',
type: 'text',
},
{
name: 'code',
type: 'text',
},
]
},
],
}
@megetron the code helps thanks! Is there a reason you're storing all the facets in one document? Instead of a document for each facet?
And also yes it definitely needs to be the
document.id
for the relationship field
ok thanks!
that's a good question actually 🙂
i am trying to design a store where you can create a filtered "Collection" to create "featured products", "best budget phones", etc..
there are some optional filters (which each filter is representd by a block):
1. filter by facets:
- color: [blue, pink, black]
- brand: [Apple, Logitech, Samsung]
- category: [Electronics, Computers, Photo]
- etc...
2. select specific products in the collection
3. filter by the product name (so you can filter by "startWith", "contains", etc..)
4. and more of this filters
so, i guess instead of creating one "facets" collection with document per each (color, brand, category) you could create a collection for each and relationship to the "products" collection.
but then, i can filter the "products" collection without saving a filter mechanism for the "collections" ("featured products", "best budget phones" etc)
thanks for your help, we can close it. i have decided to redesign.
I would take this a step further and say would be cool if an
options
callback had
siblingData
access, I have an array of selects such that I only want each option available once, such that if options are "A", "B", and "C" and they select "A" in the first array item, the next array item only has B and C available
Star
Discord
online
Get help straight from the Payload team with an Enterprise License.