CMS Development

NicolasBrito
Participant | Gold Partner
Participant | Gold Partner

I need help renderind a form with formField in react

SOLVE

I am trying to make a theme for hubspot and I need a formField to use different forms in the same template but I can't get hubspot to renderize any form!!

 

 

import React, { useState, useEffect, useRef } from 'react'
import {
  ModuleFields,
  TextField,
  ImageField,
  BooleanField,
  RepeatedFieldGroup,
  LinkField,
  FormField
} from '@hubspot/cms-components/fields'
import '../../../styles/output.css'
import logo from '../../../assets/supertekLogo.png'

/* ----------- COMPONENT ----------- */
export function Component({ fieldValues = {} }) {
  const {
    title,
    description,
    links = [],
    backgroundImage,
    useBackground,
    form_field_name
  } = fieldValues

  const [isMenuOpen, setIsMenuOpen] = useState(false)
  const [formLoading, setFormLoading] = useState(true)
  const formRef = useRef(null)

  const backgroundStyle = useBackground && backgroundImage?.src
    ? {
        backgroundImage: `url(${backgroundImage.src})`,
        backgroundSize: 'cover',
        backgroundPosition: 'center',
        backgroundRepeat: 'no-repeat',
      }
    : {}


  useEffect(() => {
    if (!formRef.current) return
   
    setFormLoading(true)
   
    // Clear the form container first
    formRef.current.innerHTML = ''
   
    // Check if we have form data
    if (!form_field_name) {
      console.log('No form field data available')
      formRef.current.innerHTML = '<p class="text-white text-center">Please configure a form in the module settings.</p>'
      setFormLoading(false)
      return
    }
   
    // Log the form data for debugging
    console.log('Form field data:', form_field_name)
   
    // Handle different possible form data structures
    let embedCode = null
   
    if (form_field_name.embed_code) {
      embedCode = form_field_name.embed_code
    } else if (form_field_name.form_id) {
      // If we have a form ID but no embed code, we might need to construct it
      embedCode = `<script charset="utf-8" type="text/javascript" src="//js.hsforms.net/forms/embed/v2.js"></script>
<script>
  hbspt.forms.create({
    region: "na1",
    portalId: "YOUR_PORTAL_ID", // You'll need to replace this with your actual portal ID
    formId: "${form_field_name.form_id}"
  });
</script>`
    } else if (typeof form_field_name === 'string') {
      embedCode = form_field_name
    }
   
    if (embedCode) {
      try {
        const wrapper = document.createElement('div')
        wrapper.innerHTML = embedCode
        formRef.current.innerHTML = ''
        while (wrapper.firstChild) {
          formRef.current.appendChild(wrapper.firstChild)
        }
       
        // If the embed code contains a script tag, we need to execute it
        const scripts = formRef.current.querySelectorAll('script')
        scripts.forEach(script => {
          const newScript = document.createElement('script')
          if (script.src) {
            newScript.src = script.src
          } else {
            newScript.textContent = script.textContent
          }
          document.head.appendChild(newScript)
        })
       
        console.log('Form rendered successfully')
        setFormLoading(false)
      } catch (error) {
        console.error('Error rendering form:', error)
        formRef.current.innerHTML = '<p class="text-white text-center">Form could not be loaded. Please check the form configuration.</p>'
        setFormLoading(false)
      }
    } else {
      console.log('No embed code found in form data')
      formRef.current.innerHTML = '<p class="text-white text-center">Please configure a form in the module settings.</p>'
      setFormLoading(false)
    }
  }, [form_field_name])

  return (
    <div className="relative w-full min-h-screen text-white dark-bg" style={backgroundStyle}>
      {/* Header */}
      <header className="flex justify-between items-center px-6 py-4 max-w-[1440px] mx-auto">
        <img src={logo} alt="Logo" className="max-w-[150px]" />

        {/* Desktop nav */}
        <nav className="hidden md:flex gap-8">
          {links.map((link, idx) => (
            <a
              key={idx}
              href={link.url?.href || '#'}
              target={link.url?.open_in_new_tab ? '_blank' : '_self'}
              rel={link.url?.no_follow ? 'nofollow' : undefined}
              className="text-white text-sm no-underline hover:text-[#A3FF12] transition"
            >
              {link.text}
            </a>
          ))}
        </nav>

        {/* Mobile burger */}
        <button
          onClick={() => setIsMenuOpen(!isMenuOpen)}
          className="md:hidden flex flex-col justify-center items-center w-8 h-8 space-y-1 z-50"
          aria-label="Toggle menu"
        >
          <span className="block w-6 h-0.5 bg-white transition-all" />
          <span className="block w-6 h-0.5 bg-white transition-all" />
          <span className="block w-6 h-0.5 bg-white transition-all" />
        </button>
      </header>

      {/* Mobile Menu */}
      <div className={`fixed inset-0 bg-black bg-opacity-95 z-40 md:hidden flex-col items-center justify-center transition-all duration-300 ${isMenuOpen ? 'flex' : 'hidden'}`}>
        <button
          className="absolute top-8 right-8 text-3xl text-white"
          onClick={() => setIsMenuOpen(false)}
          aria-label="Cerrar menú"
        >
          ✕
        </button>

        <nav className="flex flex-col items-center gap-8 text-2xl font-semibold">
          {links.map((link, idx) => (
            <a
              key={idx}
              href={link.url?.href || '#'}
              target={link.url?.open_in_new_tab ? '_blank' : '_self'}
              rel={link.url?.no_follow ? 'nofollow' : undefined}
              className="hover:text-[#A3FF12] transition-colors duration-200"
              onClick={() => setIsMenuOpen(false)}
            >
              {link.text}
            </a>
          ))}
        </nav>
      </div>

      {/* Hero + Form */}
      <section className="flex flex-col md:flex-row justify-between items-center gap-6 px-6 md:px-8 max-w-[1440px] mx-auto min-h-60vh py-12">
        <div className="flex flex-col gap-4 md:w-1/2 w-full">
          <h1 className="text-white text-7xl font-bold max-w-[600px] font-montserrat">{title}</h1>
          <p className="text-white text-xl max-w-[600px] font-montserrat">{description}</p>
        </div>
        <div className="flex flex-col justify-center gap-4 md:w-1/2 w-full">
          {formLoading && (
            <div className="flex items-center justify-center p-8">
              <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-white"></div>
              <span className="ml-3 text-white">Loading form...</span>
            </div>
          )}
          <div ref={formRef} className="min-h-[200px] flex items-center justify-center"></div>
        </div>
      </section>
    </div>
  )
}

/* ----------- FIELDS ----------- */
export const fields = (
  <ModuleFields>
    <TextField name="title" label="Title" default="Welcome to Supertek" />
    <TextField name="description" label="Description" default="Experts in ASIC repair and crypto mining technology." />
    <BooleanField name="useBackground" label="Use Background Image or GIF?" default={false} />
    <ImageField name="backgroundImage" label="Background Image or GIF" />
    <RepeatedFieldGroup
      name="links"
      label="Navigation Links"
      occurrence={{ min: 1, default: 5 }}
      default={[
        { text: 'Services', url: { url: { href: '#' }, open_in_new_tab: false, no_follow: false } },
        { text: 'About', url: { url: { href: '#' }, open_in_new_tab: false, no_follow: false } },
        { text: 'Team', url: { url: { href: '#' }, open_in_new_tab: false, no_follow: false } },
        { text: 'Testimonials', url: { url: { href: '#' }, open_in_new_tab: false, no_follow: false } },
        { text: 'FAQs', url: { url: { href: '#' }, open_in_new_tab: false, no_follow: false } },
      ]}
    >
      <TextField name="text" label="Link Text" required default="Link" />
      <LinkField
        name="url"
        label="Link URL"
        supportedTypes={[
          'EXTERNAL', 'CONTENT', 'FILE', 'EMAIL_ADDRESS', 'BLOG',
          'CALL_TO_ACTION', 'PHONE_NUMBER', 'WHATSAPP_NUMBER', 'PAYMENT',
        ]}
        showAdvancedRelOptions={true}
        default={{
          url: { content_id: null, type: 'EXTERNAL', href: '' },
          open_in_new_tab: false,
          no_follow: false,
        }}
      />
    </RepeatedFieldGroup>
    <FormField
      id="idNumber"
      name="form_field_name"
      label="Form"
      required={false}
      locked={false}
      disableInlineFormEditing={true}
      requiredPropertyTypes={['TICKET', 'COMPANY', 'CONTACT']}
      supportAllWebinarTypes={true}
      embedVersions={['v2', 'v4']}
      default={{
        response_type: 'inline',
        message: 'Thanks for submitting the form.',
      }}
    />
  </ModuleFields>
)

/* ----------- META ----------- */
export const meta = {
  label: 'Header with Navigation, Text and Form',
  category: 'headers'
}

export default Component
0 Upvotes
1 Accepted solution
BérangèreL
Solution
Community Manager
Community Manager

I need help renderind a form with formField in react

SOLVE

Hi @NicolasBrito, I hope that you are well!

Thanks for asking the HubSpot Community!

I have found similar threads that might point you in the right direction: "HELP: Embed a form in a React component" and "Pre-populating form fields with react".

I'd love to put you in touch with our Top Experts and Community Members: Hi @fabrice, @DHawkings, @EdCupaioli, @DGomez2, @SSopin, @ivanakcheurov, @PPetkov, @MJohnston2, @tjoyce, @sylvain_tirreau, @Bortami and @zach_threadint do you have suggestions to help @NicolasBrito, please?

Have a great day and thanks so much in advance for your help!
Bérangère


HubSpot’s AI-powered customer agent resolves up to 50% of customer queries instantly, with some customers reaching up to 90% resolution rates.
Learn More.


Saviez vous que la Communauté est disponible en français?
Rejoignez les discussions francophones en changeant votre langue dans les paramètres! !

View solution in original post

0 Upvotes
1 Reply 1
BérangèreL
Solution
Community Manager
Community Manager

I need help renderind a form with formField in react

SOLVE

Hi @NicolasBrito, I hope that you are well!

Thanks for asking the HubSpot Community!

I have found similar threads that might point you in the right direction: "HELP: Embed a form in a React component" and "Pre-populating form fields with react".

I'd love to put you in touch with our Top Experts and Community Members: Hi @fabrice, @DHawkings, @EdCupaioli, @DGomez2, @SSopin, @ivanakcheurov, @PPetkov, @MJohnston2, @tjoyce, @sylvain_tirreau, @Bortami and @zach_threadint do you have suggestions to help @NicolasBrito, please?

Have a great day and thanks so much in advance for your help!
Bérangère


HubSpot’s AI-powered customer agent resolves up to 50% of customer queries instantly, with some customers reaching up to 90% resolution rates.
Learn More.


Saviez vous que la Communauté est disponible en français?
Rejoignez les discussions francophones en changeant votre langue dans les paramètres! !
0 Upvotes