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.

form builder plugin: forms are created but aren't accessed to render on frontend

default discord avatar
_chadmander7 months ago
5

I am trying to get the form builder plugin working for a group project and I have gone through the docs (

https://payloadcms.com/docs/plugins/form-builder

), guide (

https://payloadcms.com/blog/create-custom-forms-with-the-official-form-builder-plugin

), youtube example (

https://www.youtube.com/watch?v=Fm4YaG__EHg

), and referenced the example code (

https://github.com/payloadcms/payload/tree/main/examples/form-builder

). I am able to create forms on the CMS but they do not render when I add them to a page. Adding in console.logs in different places confirms that the forms are created, but they are lost somewhere along the way. In the picture, at app/_components/Blocks/index.tsx, blocks returns an empty object for the form.



Please, is anyone able to help? Here is the repository:

https://github.com/michaelgolshani/oh-man-clothing-redesign-backend/tree/chad_form_builder

. At the moment, the form builder is only in the branch 'chad_form_builder'.



Thanks for the help everyone! Real life caught up to me the past couple weeks so I haven’t been on here but I should have some time soon to try this again with your help

  • discord user avatar
    dribbens
    last year

    Does your pages collection have versions enabled with drafts, if so have you published the page?



    Can you verify that the API is returning the page with the data. Compare that data to what your frontend is expecting and debug until you find the mismatch.

  • default discord avatar
    alifeinbinarylast year

    I'm having the exact same issue and have attempted the same debug methods you have

    @201951622866272256

    Did you find a solution?



    @969226489549713438

    I've checked the API call against the FormBlockType and it matches but still no data for the FormBlock is coming through. Is there a GraphQL queries missing somewhere in the codebase do you think? or is it purely REST? I'm running payload@2.9.0 and plugin-form-builder^1.2.0. Followed the guide here (

    https://payloadcms.com/blog/create-custom-forms-with-the-official-form-builder-plugin

    ) and the example repo to the letter, I believe.



    My project is a clone of the e-commerce example repo, which I'm trying to add forms to. Forgive me, this is my first Payload project, so I'm still getting my bearings with the CMS



    Since Forms don't seem to populate on a page when following the guide or Youtube tutorial, I've added this export to

    ./src/app/_graphql/

    export const FORM_BLOCK = `
    ...on FormBlock {
      blockType
      enableIntro
      introContent
      ${FORM}
    }


    And created

    ./src/app/_graphql/form.ts
    export const FORM = ` form {
        id
        title
        submitButtonLabel
        confirmationType
        confirmationMessage
        fields {
          name
          label
          required
          width
          blockName
          blockType
        }
    }


    And amended the PAGE query in

    ./src/app/_graphql/pages.ts

    to include the ${FORM_BLOCK} in the layout object.



    But now I'm getting a 404 error...



    @231946132949827584

    I came to the same solution last night after using yarn generate:types and gradually building out the query using hoppscotch at the /api/graphql endpoint. Smart minds think alike!



    The only field I’ve not been able to add to the query is defaultValue. Obviously you can define this in the form builder and the property gets stored to the database, however, adding it to the query I get a type error.



    Also, I had to add type=“submit” to the Button in order to get the form to POST, which I assume you did as well if you’ve got working forms.



    Also, I had to make ./src/app/_components/Blocks/Form/index.tsx 'use client' and change that useRouter reference to next/navigation



    The RichText message is broken upon sending the form. Are you experiencing the same thing?



    This is the error I see in the browser console


    Warning: Cannot update a component (

    HotReload

    ) while rendering a different component (

    RichText

    ). To locate the bad setState() call inside

    RichText

    , follow the stack trace as described in

    https://reactjs.org/link/setstate-in-render

    RichText@webpack-internal:///(app-pages-browser)/./src/app/_components/RichText/index.tsx:13:34



    Quick question, are you using the lexical editor or slate editor? I think my error arose from switching to the Lexical editor. I had to drill down on a prop to access the underlying array that the RichText component was expecting. Just giving you a heads up in case you experience the same thing upon migrating.



    My

    ./src/app/_components/Blocks/Form/index.tsx

    looks like this from lines lines 140-145 Notice the RichText component that gets rendered for a

    confirmationType === 'message'

    , the content has to be access from

    confirmationMessage.root.children

    .



    {!isLoading && hasSubmitted && confirmationType === 'message' && (
      <RichText
        className={classes.confirmationMessage}
        content={confirmationMessage.root.children}
      />
    )}


    All good dude. Happy we all managed to get to the solution 🙂 Mark it as solved if you can.



    I'm in the process of submitting a PR to the templates/ subdirectory of the main repo with the updates. It depends on when/if the changes get approved by the Payload team but I'll be submitting them very soon



    PR related to this thread:

    https://github.com/payloadcms/payload/pull/5199
  • default discord avatar
    anxietybyteslast year
    @411047128673288192

    I think I have this fixed. I was hitting the same issues you and

    @201951622866272256

    were having.



    I saw in the console there was an error was complaining that it

    Cannot query field "name" on type "Form_Fields". Did you mean to use an inline fragment on "Checkbox", "Country", "Email", "Number", or "Select"?

    whenever you see the 404 error in the web.



    Using that I changed the

    ./src/app/_graphql/form.ts

    to the following:


    export const FORM_FIELDS = `
      ... on Checkbox { blockName blockType label name required width }
      ... on Country { label name required width }
      ... on Email { blockName blockType label name required width }
      ... on Message { blockName blockType message }
      ... on Select { blockName blockType label name options { label value } required width }
      ... on State { blockName blockType label name required width }
      ... on Text { blockName blockType label name required width }
      ... on Textarea { blockName blockType label name required width }
      ... on Number { blockName blockType label name required width }
      `
    
    export const FORM =  `form {
        id
        title
        submitButtonLabel
        confirmationType
        confirmationMessage
        fields {... on Form_Fields { ${FORM_FIELDS} }}
    }`


    You can find the valid form fields and their properties within

    ./src/payload/payload_types.ts

    I used this to 'fill in the blanks' per say.


    With these changes, I have functioning forms.



    (edit): I also had to add the

    type="submit"

    to make the button submit the form


    I'm seeing the same thing as far as adding the defaultValue to the query.



    Getting an error:

    Error: Fields "defaultValue" conflict because they return conflicting types "Boolean" and "String". Use different aliases on the fields to fetch both if this was intentional.



    Which from

    payload-types.ts

    there are

    number

    ,

    boolean

    and

    string

    values returned from each of the fields and this is why graphQL is complaining to us, it wants one return type per field name. I'm looking into this as well, I've gotten

    Text

    ,

    TextArea

    and

    Select

    fields to return the default values, but nothing else so far without returning the error mentioned above.



    I had thought that keeping everything in one

    export

    field made things look messy and I was under the presumption that graphql would read the

    defaultValue

    as required per field, that is not the case however. My

    form.ts

    file looks like the following:



    export const CHECKBOX_FIELD = ` 
    ... on Checkbox { 
      blockName 
      blockType 
      label 
      name 
      required 
      width 
    }
    `
    
    export const TEXT_FIELD = `
    ... on Text { 
      blockName 
      blockType 
      label 
      name 
      required 
      width 
      defaultValue 
    }
    `
    
    export const TEXTAREA_FIELD = `
    ... on Textarea { 
      blockName 
      blockType 
      label 
      name 
      required 
      width 
      defaultValue 
    }
    `
    
    export const SELECT_FIELD = `
    ... on Select { 
      blockName 
      blockType 
      label 
      name 
      required 
      width 
      options { label value }
      defaultValue 
    }
    `
    
    export const EMAIL_FIELD = `
    ... on Email { 
      blockName 
      blockType 
      label 
      name 
      required 
      width 
    }
    `
    
    export const STATE_FIELD = `
    ... on State { 
      blockName 
      blockType 
      label 
      name 
      required 
      width 
    }
    `
    
    export const COUNTRY_FIELD = `
    ... on Country { 
      blockName 
      blockType 
      label 
      name 
      required 
      width 
    }
    `
    
    export const MESSAGE_FIELD = `
    ... on Message { 
      blockName 
      blockType 
      message 
    }
    `
    
    export const FORM_FIELDS = `
      ... on Checkbox { ${CHECKBOX_FIELD}  }
      ... on Country { ${COUNTRY_FIELD} }
      ... on Email { ${EMAIL_FIELD} }
      ... on Message { ${MESSAGE_FIELD} }
      ... on Select { ${SELECT_FIELD} }
      ... on State { ${STATE_FIELD} }
      ... on Text { ${TEXT_FIELD} }
      ... on Textarea { ${TEXTAREA_FIELD} }
      `
    
    export const FORM =  `form {
        id
        title
        submitButtonLabel
        confirmationType
        confirmationMessage
        fields {... on Form_Fields { ${FORM_FIELDS} }}
    }`


    @411047128673288192


    To your first message, yes, I also had to add

    'use client'

    and swap the

    useRouter

    to

    next/navigation

    To your second message: I'm not seeing where the rich text field is broken upon form submission. What I place in the textArea is what appears in the admin panels form submissions on my side. What are you seeing on your end? I did get the defaultValue to appear in the textArea though, I did have to go into the textArea component and and the defaultValue into it. I'll link that code below.



    On the third message: I've seen this error as well, typically when I am changing code of the page also viewing in the browser. A hard refresh of the page fixes it for me, CTRL + SHIFT + R is the keyboard shortcut for windows.



    TextArea component with defaultValue added:


    export const Textarea: React.FC<
      TextField & {
        register: UseFormRegister<FieldValues & any>
        defaultValue?: string
        rows?: number
        errors: Partial<
          FieldErrorsImpl<{
            [x: string]: any
          }>
        >
      }
    > = ({ name, label, width, defaultValue = "Your text here.", rows = 3, register, required: requiredFromProps, errors }) => {
      return (
        <Width width={width}>
          <div className={classes.wrap}>
            <label htmlFor={name} className={classes.label}>
              {label}
            </label>
            <textarea
              rows={rows}
              className={classes.textarea}
              id={name}
              defaultValue={defaultValue}
              {...register(name, { required: requiredFromProps })}
            />
            {requiredFromProps && errors[name] && <Error />}
          </div>
        </Width>
      )
    }


    I'm using the slate editor for now. I don't have any plans to use the lexical editor as of now.



    I also dusted off my HTML skills and replaced the

    defaultValue={defaultValue}

    to

    placeholder={defaultValue}

    This got the defaultValue to appear in the

    input

    fields better, text will auto clear on typing rather than clearing the box by manually.

  • default discord avatar
    koffee_rslast year
    @411047128673288192

    Would it be possible you upload a boilerplate with working form to GH? Because I got the exact same issue atm 😄

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.