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.

custom field value not being saved

default discord avatar
revyn_.3 years ago
14

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 />;
};
  • discord user avatar
    jarrod_not_jared
    3 years ago

    What’s the config look like for field and its parent fields look like?

  • default discord avatar
    revyn_.3 years ago

    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,
            },
          },
        },
      ],
    };


    @281120856527077378

    nevermind, i figured it was because the

    fieldtype

    was

    ui

    I changed it to text and now it's working >.<'

  • discord user avatar
    jarrod_not_jared
    3 years ago

    NICE



    happy to help



    🤣

  • default discord avatar
    revyn_.3 years ago

    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.tsx


    But 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

  • discord user avatar
    jarrod_not_jared
    3 years ago

    Where are you using

    components/RenderBlocks/index.tsx

    ? in NextJS?

  • default discord avatar
    revyn_.3 years ago

    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].tsx
  • discord user avatar
    jarrod_not_jared
    3 years ago

    Is

    /blocks/index.ts

    exporting configs and JSX blocks?

  • default discord avatar
    revyn_.3 years ago

    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

  • discord user avatar
    jarrod_not_jared
    3 years ago

    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

  • default discord avatar
    revyn_.3 years ago

    that's odd because that was never an issue before



    only since I added my custom field to the config

  • discord user avatar
    jarrod_not_jared
    3 years ago

    right, which uses a payload component, that references the global scss file

  • default discord avatar
    revyn_.3 years ago

    does the

    useField

    part do that?

  • discord user avatar
    jarrod_not_jared
    3 years ago

    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

  • default discord avatar
    revyn_.3 years ago

    Alright, then I'll do the the seperation - thank you ❤️

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.