I have created a custom field which is supposed to retrieve data from a global collection and then make "selectable" which of those items to display.
I tried to follow the docs as good as possible, but here I am stuck, I assume it has to do with the fact that the fieldname is missing? How could I set that?
import React, { useEffect, useState } from 'react';
import { Label, useField } from 'payload/components/forms';
import { Props } from 'payload/components/fields/Text';
const SelectFromFAQ:React.FC<Props> = ({ label, required, path }) => {
const [faqItems, setFaqItems] = useState(null);
const usePath = `${path}.selected`;
const { value = '', setValue } = useField({ path: usePath });
useEffect(() => {
const fetchData = async () => {
const data = await fetch(`${process.env.PAYLOAD_PUBLIC_SERVER_URL}/papi/globals/faq`, {
headers: { 'Content-Type': 'application/json' },
});
const json = await data.json();
if (json?.groups) {
setFaqItems(json.groups);
}
};
fetchData().catch(console.error);
}, []);
if (faqItems) {
return (
<React.Fragment>
<Label
htmlFor={path}
label={label}
required={required}
/>
<ul style={{ margin: 0, padding: 0 }}>
{faqItems.map((item, index) => (
<li
key={index}
style={{ listStyle: 'none', margin: 0, padding: 0 }}
>
<button
type="button"
key={item.id}
onClick={() => setValue(item.id)}
className={`${item.id === value ? 'btn--selected' : ''} btn btn--style-primary btn--icon-style-without-border btn--size-small btn--icon-position-right`}
style={{ margin: '5px 0' }}
>
{item.title}
</button>
</li>
))}
</ul>
</React.Fragment>
);
}
return <React.Fragment />;
};What’s the config look like for field and its parent fields look like?
This is the config for my global collection:
import { GlobalConfig } from 'payload/types';
const FAQ: GlobalConfig = {
slug: 'faq',
access: {
read: () => true,
},
fields: [
{
name: 'groups',
type: 'array',
admin: {
components: {
RowLabel: ({ data, index, path }) => data?.title || `FAQ ${String(index).padStart(2, '0')}`,
},
},
fields: [
{
type: 'text',
name: 'title',
},
{
name: 'items',
type: 'array',
admin: {
components: {
RowLabel: ({ data, index, path }) => data?.question || `FAQ ${String(index).padStart(2, '0')}`,
},
},
fields: [
{
type: 'text',
label: 'Frage',
name: 'question',
},
{
type: 'richText',
label: 'Antwort',
name: 'answer',
},
],
},
],
},
],
};
export default FAQ;The config for my field is what I posted initially, and the block / parent? is as follows:
import { Block } from 'payload/types';
import { Faq } from '../../payload-types';
import SelectFromFAQ from '../../collections/uiFields/selectFromGlobalFAQ/field';
export type FAQBlockType = {
blockType: 'faqblock'
blockName?: string
width?: 'fullwidth' | 'container'
headline?: string
subline?: string
faqItems: Faq[]
}
export const FAQBlock: Block = {
slug: 'faqblock',
labels: {
singular: 'FAQ Accordion',
plural: 'FAQ Accordions',
},
fields: [
{
type: 'row',
fields: [
{
name: 'width', // required
type: 'select', // required
label: 'Breite',
hasMany: false,
admin: {
isClearable: false,
},
defaultValue: 'container',
options: [
{
label: 'Container',
value: 'container',
},
{
label: 'Bildschirm',
value: 'fullwidth',
},
],
},
],
},
{
type: 'row',
fields: [
{
label: 'Headline',
name: 'headline',
type: 'text',
},
{
label: 'Subline',
name: 'subline',
type: 'textarea',
},
],
},
{
type: 'ui',
name: 'faqItems',
label: 'FAQ Items',
admin: {
components: {
Field: SelectFromFAQ,
},
},
},
],
};nevermind, i figured it was because the
fieldtypewas
uiI changed it to text and now it's working >.<'
NICE
happy to help
🤣
I get a new error now though :x
for some reason nextjs thinks that I am importing global css styles - this is the error:
error - ./node_modules/payload/dist/admin/components/elements/Button/index.scss
Global CSS cannot be imported from within node_modules.
Read more: https://nextjs.org/docs/messages/css-npm
Location: node_modules\payload\dist\admin\components\elements\Button\index.js
Import trace for requested module:
./node_modules/payload/dist/admin/components/elements/Button/index.scss
./node_modules/payload/dist/admin/components/elements/Button/index.js
./node_modules/payload/dist/admin/components/forms/Submit/index.js
./node_modules/payload/components/forms.ts
./collections/uiFields/selectFromGlobalFAQ/field.tsx
./blocks/FaqBlock/config.ts
./blocks/index.ts
./components/RenderBlocks/index.tsxBut I am not importing the Button or any CSS from payload.
The only thing I am doing is to import the Label and use already present css classes from payload but for some reason I can't seem to figure
Where are you using
components/RenderBlocks/index.tsx? in NextJS?
Its basically just a wrapper component to render each block in the frontend
'use client';
import React from 'react';
import Container from 'react-bootstrap/Container';
import { Layout } from '../../collections/Page';
import { components } from '../../blocks';
import classes from './index.module.css';
type Props = {
layout: Layout[]
className?: string
}
const RenderBlocks: React.FC<Props> = ({ layout, className }) => (
<div className={[
classes.renderBlocks,
className,
].filter(Boolean).join(' ')}
>
{layout.map((block, i) => {
const Block = block.blockType === 'hero' ? components.DynamicHero : components[block.blockType];
if (Block) {
if (block.blockType === 'hero' || block?.width === 'fullwidth') {
return (
<Block
{...block}
key={i}
/>
);
}
return (
<Container
key={i}
className={classes.block}
>
<Block {...block} />
</Container>
);
}
return null;
})}
</div>
);
export default RenderBlocks;its used for my pages within my
[...slug].tsxIs
/blocks/index.tsexporting configs and JSX blocks?
yes
import dynamic from 'next/dynamic';
import { CallToAction } from './CallToAction/index';
import { Content } from './Content';
import { Image } from './Image';
import { FeaturedProducts } from './FeaturedProducts';
import { Hero } from './Hero/index';
import { ThreeIconGrid } from './ThreeIconGrid';
import { NearbyLocations } from './NearbyLocations';
import { FeaturedLocations } from './FeaturedLocations/config';
import { FAQBlock } from './FaqBlock/config';
const DynamicHero = dynamic(() => import('./Hero/component').then((mod) => mod.Component), { ssr: false });
const cta = dynamic(() => import('./CallToAction/component').then((mod) => mod.Component), { ssr: false });
const nearbylocations = dynamic(() => import('./NearbyLocations/component').then((mod) => mod.Component), { ssr: false });
const content = dynamic(() => import('./Content/component').then((mod) => mod.Component), { ssr: false });
const image = dynamic(() => import('./Image/component').then((mod) => mod.Component), { ssr: false });
const featuredProducts = dynamic(() => import('./FeaturedProducts/component').then((mod) => mod.Component), { ssr: false });
const threeicongrid = dynamic(() => import('./ThreeIconGrid/component').then((mod) => mod.Component), { ssr: false });
const featuredLocations = dynamic(() => import('./FeaturedLocations').then((mod) => mod.Component), { ssr: false });
const faqBlock = dynamic(() => import('./FaqBlock').then((mod) => mod.Component), { ssr: false });
export const collections = {
CallToAction,
Content,
Image,
FeaturedProducts,
Hero,
ThreeIconGrid,
NearbyLocations,
FeaturedLocations,
FAQBlock,
};
export const components = {
cta,
content,
image,
featuredProducts,
DynamicHero,
threeicongrid,
nearbylocations,
featuredLocations,
faqBlock,
};this is my basic component for the faq block:
import React from 'react';
import Col from 'react-bootstrap/Col';
import Row from 'react-bootstrap/Row';
import Container from 'react-bootstrap/Container';
import type { FAQBlockType } from './config';
export const Component:React.FC<FAQBlockType> = (props) => {
console.log(props);
return <div>Hello World</div>;
};which should not throw that error
I think you will need to separate them so configs and blocks are not exported from the same file
your frontend is loading the configs (bc you are importing the barrel file) which have global scss files, and next will not allow that
that's odd because that was never an issue before
only since I added my custom field to the config
right, which uses a payload component, that references the global scss file
does the
useFieldpart do that?
It stems from the
import { Label, useField } from 'payload/components/forms';inside your custom component
Which is a barrel file, that import/exports the Submit button, which loads a global scss file. I am just following the path upwards from the error you posted above
Alright, then I'll do the the seperation - thank you ❤️
Star
Discord
online
Get dedicated engineering support directly from the Payload team.