How to Find and Render the Handle in a User Folder?

I am trying to figure out how to render the user’s account from the sign-up and login forms, but I do not see where the [handle].tsx file is being imported.

The form has been created for sign-up and login. Now, it’s time to figure out how to import it into the page correctly because I am getting lost regarding where I need to import it into the page and how the file structure has been laid out.

What would be a better idea for the form? Should I create it as a component that can be used on other pages, or should I just render it in the [handle].tsx file? @manish-sharma

Hello @xbrandonpowell,

If you anticipate needing the sign-up and login forms on multiple pages or if you plan to expand your application in the future with additional forms, creating a reusable component would be advantageous. This allows you to maintain consistency throughout your application and avoid duplicating code.

Separating your form component from your page logic can help keep your codebase organized and easier to maintain. It also adheres to the principle of single responsibility, where each component or file is responsible for a specific task.

With these considerations in mind, here are two approaches you could take:

1. Create a Reusable Form Component

File Structure:

components/
  ├── forms/
  │    ├── SignUpForm.tsx
  │    └── LoginForm.tsx
  └── ...

Usage:

// [handle].tsx
import SignUpForm from '../components/forms/SignUpForm';
import LoginForm from '../components/forms/LoginForm';

const HandlePage = () => {
  return (
    <div>
      <SignUpForm />
      <LoginForm />
    </div>
  );
};

2. Render Forms in the Page Component

File Structure:

pages/
  ├── handle.tsx
  └── ...

Usage:

// handle.tsx
import SignUpForm from '../components/forms/SignUpForm';
import LoginForm from '../components/forms/LoginForm';

const HandlePage = () => {
  return (
    <div>
      <SignUpForm />
      <LoginForm />
    </div>
  );
};

If you anticipate needing the forms on multiple pages or want to follow a more modular approach, creating reusable components is recommended. However, if the forms are specific to the [handle] page and are unlikely to be reused elsewhere, rendering them directly in the page component might be simpler.

Consider your project requirements, future scalability, and maintenance needs when deciding between these approaches.

Thanks,

1 Like

Thank you @manish-sharma for everything my friend.

Hey @manish-sharma ,

Make sure I did this correctly because created components little different when you are building a Shopify website from doing a static website:

But import builder components are different from doing nextjs builder from shopify builder theme but trying figure this out.

'use client';
import React from 'react';
import { Builder } from '@builder.io/sdk';
import { withBuilder } from '@builder.io/react';
// import { withBuilder } from '../../functions/with-builder';

export interface SignUpFormProps {}

class SignUpFormComponent extends React.Component<SignUpFormProps> {
  render() {
    return (
      <form>
        <label>Full Name:</label>
        <FormInput type="text" name="name" placeholder="Enter your name" />

        <label>Email:</label>
        <FormInput type="email" name="email" placeholder="Enter your email" required />

        <label>Password:</label>
        <FormInput type="password" name="password" placeholder="Enter your password" required />

        <label>Date of Birth:</label>
        <FormInput type="date" name="dob" placeholder="Enter your date of birth" required />

        <label>Phone:</label>
        <FormInput type="tel" name="phone" placeholder="Enter your phone number" required />

        <button type="submit">Sign Up</button>
      </form>
    );
  }
}

export const SignUpForm = withBuilder(SignUpFormComponent, {
  name: 'Form:SignUp',
  noWrap: true,
  static: true,
});

interface FormInputProps {
  type?: string;
  attributes?: any;
  name?: string;
  value?: string;
  placeholder?: string;
  defaultValue?: string;
  required?: boolean;
}

class FormInputComponent extends React.Component<FormInputProps> {
  render() {
    return (
      <input
        key={Builder.isEditing && this.props.defaultValue ? this.props.defaultValue : 'default-key'}
        placeholder={this.props.placeholder}
        type={this.props.type}
        name={this.props.name}
        value={this.props.value}
        defaultValue={this.props.defaultValue}
        required={this.props.required}
        {...this.props.attributes}
      />
    );
  }
}

export const FormInput = withBuilder(FormInputComponent, {
  name: 'Form:Input',
  inputs: [
    {
      name: 'type',
      type: 'text',
      enum: [
        'text',
        'number',
        'email',
        'url',
        'checkbox',
        'radio',
        'range',
        'date',
        'datetime-local',
        'search',
        'tel',
        'time',
        'file',
        'month',
        'week',
        'password',
        'color',
        'hidden',
      ],
      defaultValue: 'text',
    },
    {
      name: 'name',
      type: 'string',
      required: true,
      helperText:
        'Every input in a form needs a unique name describing what it takes, e.g. "email"',
    },
    {
      name: 'placeholder',
      type: 'string',
      defaultValue: 'Hello there',
      helperText: 'Text to display when there is no value',
    },
    {
      name: 'defaultValue',
      type: 'string',
    },
    {
      name: 'value',
      type: 'string',
      advanced: true,
    },
    {
      name: 'required',
      type: 'boolean',
      helperText: 'Is this input required to be filled out to submit a form',
      defaultValue: false,
    },
  ],

  noWrap: true,
  static: true,
  defaultStyles: {
    paddingTop: '10px',
    paddingBottom: '10px',
    paddingLeft: '10px',
    paddingRight: '10px',
    borderRadius: '3px',
    borderWidth: '1px',
    borderStyle: 'solid',
    borderColor: '#ccc',
  },
});

Hello @xbrandonpowell,

The code seems to be correct and your builder import depends on the builder SDK version you are using.

Your imports should be from ‘@builder.io/react’

e.g

import { Builder, builder } from "@builder.io/react";

To know about the builder API versions you can refer to the below link

But what do understand is that stuck in figuring out how to improve in the builder because like I said it’s different from the way I was doing it the first time so now trying to find out why does not show up in the builder.

Make sure you updated your changes in code if you all going:

Hello @xbrandonpowell,

Can you confirm the exact issue you are facing currently? Is the SignUpFormComponent not showing in the builder editor?

Hey @manish-sharma

I created an video:

Hello @xbrandonpowell,

You can find an example of registering a custom component here

Additionally, you can check the Product view example of the custom component which shows how to register the component with the builder

Hey @manish-sharma

You talk in this post saying that there is a place to test your component and visit any page in your web browser that renders this component, but there is no page on localhost that allows me to test my component.

Like I keep on saying before there was a place where could test my component but when I install the shopify builder theme it’s different.

That where the confusion lies there no consistency in building this different shopify builder theme if him using nextjs theme or shopify is two different setup process when you launch a new project.

'use client';
import React from 'react';
import { Builder, withChildren } from "@builder.io/react";';

// pass your custom component to withChildren()
const SignUpWithBuilderChildren = withChildren(SignUp)

// specify defaultChildren when you register the component
Builder.registerComponent(SignUpWithBuilderChildren, {
  name: 'Form', // Name of the component
  image: 'https://cdn.builder.io/api/v1/image/assets%2FIsxPKMo2gPRRKeakUztj1D6uqed2%2Fad6f37889d9e40bbbbc72cdb5875d6ca', // Image for the component
  inputs: [

    // List of input options for the component
    {
      name: 'type',
      type: 'text',
      enum: [ // Possible input types
        'text',
        'number',
        'email',
        'url',
        'checkbox',
        'radio',
        'range',
        'date',
        'datetime-local',
        'search',
        'tel',
        'time',
        'file',
        'month',
        'week',
        'password',
        'color',
        'hidden',
      ],
      
      defaultValue: 'text', // Default input type
    },

    {
      name: 'name',
      type: 'string',
      required: true,
      helperText: 'Every input in a form needs a unique name describing what it takes, e.g. "email"', // Helper text for input name
    },

    {
      name: 'placeholder',
      type: 'string',
      defaultValue: 'Hello there',
      helperText: 'Text to display when there is no value', // Helper text for placeholder
    },

    {
      name: 'defaultValue',
      type: 'string',
    },

    {
      name: 'value',
      type: 'string',
      advanced: true,
    },

    {
      name: 'required',
      type: 'boolean',
      helperText: 'Is this input required to be filled out to submit a form',
      defaultValue: false, // Default value for required
    },
  ],

  noWrap: true, // Prevent wrapping
  static: true, // Component is static

  defaultStyles: {

    // Default styles for the component
    paddingTop: '10px',
    paddingBottom: '10px',
    paddingLeft: '10px',
    paddingRight: '10px',
    borderRadius: '3px',
    borderWidth: '1px',
    borderStyle: 'solid',
    borderColor: '#ccc',
  },
  
  // Adding defaults is important for easy usability
  defaultChildren: [
    { 
      '@type': '@builder.io/sdk:Element',
      component: { name: 'Text', options: { text: 'I am child text block!' } }
    }
  ]
})

// Interface for props of FormInput component
export interface SignUpFormInputProps {
  type?: string;
  attributes?: any;
  name?: string;
  value?: string;
  placeholder?: string;
  defaultValue?: string;
  required?: boolean;
}

// Component for input field in a form
class FormInputComponent extends React.Component<SignUpFormInputProps> {
  render() {
    return (
      <input
        // Key for input, changes based on editing state and default value
          key={Builder.isEditing && this.props.defaultValue ? this.props.defaultValue : 'default-key'}
          placeholder={this.props.placeholder}
          type={this.props.type}
          name={this.props.name}
          value={this.props.value}
          defaultValue={this.props.defaultValue}
          required={this.props.required}

        // Spread additional attributes
          {...this.props.attributes}
      />
    );
  }
}

Hello @xbrandonpowell,

Registering components and testing them should follow the same process regardless of whether you’re using React, Next.js, or Shopify. The component registration process remains consistent across these platforms, and if done correctly, the component should appear in the editor as expected.

If you encounter any specific issues during the registration or testing process, feel free to provide more details, and we’ll be happy to assist you further.