BuzzForm
BuzzFormDocs

Custom Rendering

Use custom components to render fields while keeping BuzzForm's validation and state management.

Custom Rendering

BuzzForm lets you use custom components for any field. You can replace just the input or the entire field including wrapper and label.

Custom Input Only

Use the input prop to replace just the input element. BuzzForm handles the label, description, and error display:

{
  type: "text",
  name: "color",
  label: "Favorite Color",
  input: (props) => (
    <input
      type="color"
      id={props.id}
      value={props.value || "#000000"}
      onChange={(e) => props.onChange(e.target.value)}
      onBlur={props.onBlur}
      disabled={props.disabled}
    />
  ),
}

Input Props

PropTypeDescription
fieldFieldThe field configuration
pathstringField path (e.g., "email", "address.city")
idstringHTML id for label association
namestringHTML name for autofill
valueTCurrent field value
onChange(value: T) => voidUpdate the value
onBlur() => voidMark field as touched
disabledbooleanWhether field is disabled
readOnlybooleanWhether field is read-only
errorstringValidation error message
autoFocusbooleanWhether to auto-focus

Full Custom Component

Use the component prop to replace the entire field, including wrapper, label, and error handling:

{
  type: "text",
  name: "rating",
  label: "Rating",
  component: (props) => (
    <div className="space-y-2">
      <label htmlFor={props.id}>{props.field.label}</label>
      <StarRating
        value={props.value}
        onChange={props.onChange}
        max={5}
      />
      {props.error && (
        <p className="text-sm text-destructive">{props.error}</p>
      )}
    </div>
  ),
}

Component Props

PropTypeDescription
fieldFieldThe field configuration
pathstringField path
idstringHTML id
formFormAdapterForm adapter instance
valueTCurrent field value
onChange(value: T) => voidUpdate the value
onBlur() => voidMark as touched
disabledbooleanDisabled state
readOnlybooleanRead-only state
errorstringValidation error
autoFocusbooleanAuto-focus flag

When to Use Which

Use CaseApproach
Different input element (color picker, slider)input prop
Third-party component integrationinput prop
Custom layout/styling for one fieldcomponent prop
Custom error displaycomponent prop
Adding extra elements around inputcomponent prop

Examples

Rich Text Editor

import { Editor } from "@tiptap/react";

{
  type: "textarea",
  name: "content",
  label: "Content",
  input: (props) => (
    <RichTextEditor
      content={props.value}
      onUpdate={(html) => props.onChange(html)}
      onBlur={props.onBlur}
      editable={!props.disabled && !props.readOnly}
    />
  ),
}

Date Picker with Calendar

{
  type: "date",
  name: "appointmentDate",
  label: "Appointment Date",
  input: (props) => (
    <CustomCalendar
      selected={props.value}
      onSelect={props.onChange}
      minDate={new Date()}
      disabled={props.disabled}
    />
  ),
}

Slider Input

{
  type: "number",
  name: "volume",
  label: "Volume",
  min: 0,
  max: 100,
  input: (props) => (
    <div className="flex items-center gap-4">
      <Slider
        value={[props.value ?? 50]}
        onValueChange={([v]) => props.onChange(v)}
        min={props.field.min}
        max={props.field.max}
        disabled={props.disabled}
      />
      <span className="w-12 text-right">{props.value ?? 50}%</span>
    </div>
  ),
}

File Input with Preview

{
  type: "upload",
  name: "avatar",
  label: "Profile Picture",
  component: (props) => (
    <div className="space-y-4">
      <label>{props.field.label}</label>
      <div className="flex items-center gap-4">
        {props.value && (
          <img
            src={URL.createObjectURL(props.value)}
            className="w-16 h-16 rounded-full object-cover"
          />
        )}
        <input
          type="file"
          accept="image/*"
          onChange={(e) => props.onChange(e.target.files?.[0])}
          disabled={props.disabled}
        />
      </div>
      {props.error && (
        <p className="text-sm text-destructive">{props.error}</p>
      )}
    </div>
  ),
}

On this page