When registering custom components to use within data entries, add the showIf
key to inputs to dynamically modify what attributes are editable for the component.
- Dynamically hide and show inputs for a registered component.
- Leverage the
options
object for dynamic statements.
This tutorial results in a CustomHeader
registered component that displays banner text with an optional background image. Inputs dynamically adjust based on the component's state.
An example video demonstrating this functionality is below.
To complete this tutorial, you need:
- An integrated page or section already connected to Builder.
Begin by creating a new registered component in your codebase.
Create a new CustomHeader.tsx
file. The location of this file depends on your file structure, but it should be accessible from one of your connected pages.
Within the file, create the shell of your registered component.
"use client";
import type { RegisteredComponent } from "@builder.io/sdk-react";
export function CustomHeader() {
return (
<h1>My Custom Header</h1>
);
}
export const customHeaderInfo: RegisteredComponent = {
component: CustomHeader,
name: "CustomHeader"
};
This file:
- imports the
RegisteredComponent
type from Builder's SDK - creates a new component called
CustomHeader
with anh1
element inside of it - exports the registered component as an object, referencing the component and providing a name for it
Within one of your integrated pages, import your registered component.
import { customHeaderInfo } from "../../components/CustomHeader";
To confirm your component has been registered with Builder:
- Open up your integrated page within Builder.
- Open the Custom Components panel within the Insert tab.
- Drag the Custom Header block to an available space on your page.
If working correctly, you should see your h1
element's text appear on your page.
Tip: As you continue in the tutorial, you may notice some changes from your registered component do not immediately reflect within Builder.
While Builder watches for stylistic changes, updates to the exported registered component may require a refresh of your Builder content entry within the browser.
Next, add styles to your component so that it appears as you'd like. For now, the colors and text within the component remain static.
Replace the CustomHeader component with the code below. This code adds a small amount of styling to the header.
export function CustomHeader() {
return (
<h1
style={{
background: "#CCCCCC",
lineHeight: 1.4,
padding: "120px 50px 50px",
}}
>
<span
style={{
backgroundColor: "black",
color: "white",
display: "inline",
padding: "0.5rem",
boxDecorationBreak: "clone",
}}
>
My Custom Header
</span>
</h1>
);
}
Return to your integrated page on Builder. There, you should see your component is updated.
Add inputs to your registered component, to adjust the style and text of your header from within Builder's Visual Editor.
First, define the parts of your component you wish to be dynamic within your registered component by doing the following:
- Add an
inputs
key to the registered component. The value should be an array. - Within your inputs array, create an object with the following keys:
name
,type
, anddefaultValue
. For more details on input types, see Input types for custom components. - Fill in the values for those keys for each adjustable value within your registered component.
In the code example below, the title is made adjustable along with all colors within the header.
export const customHeaderInfo: RegisteredComponent = {
component: CustomHeader,
name: "CustomHeader",
inputs: [
{ name: "title", type: "text", defaultValue: "My Title" },
{ name: "titleColor", type: "color", defaultValue: "#FFFFFF" },
{ name: "titleBackgroundColor", type: "color", defaultValue: "#000000" },
{ name: "backgroundColor", type: "color", defaultValue: "#CCCCCC" },
],
};
Now, use those inputs within your component. First, define a TypeScript interface for your components props, as seen in the code example below.
interface CustomHeaderProps {
title: string;
titleColor: string;
titleBackgroundColor: string;
backgroundColor: string;
}
Next, access the inputs through props within your component. Replace hardcoded values with prop values.
export function CustomHeader({
title,
titleColor,
titleBackgroundColor,
backgroundColor,
}: CustomHeaderProps) {
return (
<h1
style={{
background: backgroundColor,
lineHeight: 1.4,
padding: "120px 50px 50px",
}}
>
<span
style={{
backgroundColor: titleBackgroundColor,
color: titleColor,
display: "inline",
padding: "0.5rem",
boxDecorationBreak: "clone",
}}
>
{title}
</span>
</h1>
);
}
Your registered component should look the same when first added to your content entry. However, within the Options tab, you can now adjust the title and various colors of the header.
Tip: Remember, you might need to refresh to see your changes. If your component does not automatically update, Remove the component and then add a fresh copy from the Custom Components panel.
You now have a functional registered custom component that is editable within Builder. Now it's time to transform the registered component by adding conditional inputs that are dependent on the values of other inputs.
First, add new inputs that relate to setting a background image within the header as opposed to just a single color.
In the code example below, three new inputs are added to the registered component.
export const customHeaderInfo: RegisteredComponent = {
component: CustomHeader,
name: "CustomHeader",
inputs: [
{ name: "title", type: "text", defaultValue: "My Title" },
{ name: "titleColor", type: "color", defaultValue: "#FFFFFF" },
{ name: "titleBackgroundColor", type: "color", defaultValue: "#000000" },
{ name: "backgroundColor", type: "color", defaultValue: "#CCCCCC" },
// New inputs
{ name: "backgroundImage", type: "url", defaultValue: "" },
{ name: "backgroundPositionX", type: "text", defaultValue: "100%" },
{ name: "backgroundPositionY", type: "text", defaultValue: "25%" },
],
};
Next, update the TypeScript interface with these new inputs.
interface CustomHeaderProps {
title: string;
titleColor: string;
titleBackgroundColor: string;
backgroundColor: string;
backgroundImage: string;
backgroundPositionX: string;
backgroundPositionY: string;
}
Then update your component to account for these new inputs. In the code below, if there is a value within the backgroundImage
property, a background image is shown. Otherwise, the background color is shown.
export function CustomHeader({
title,
titleColor,
titleBackgroundColor,
backgroundColor,
backgroundImage,
backgroundPositionX,
backgroundPositionY,
}: CustomHeaderProps) {
return (
<h1
style={{
background:
backgroundImage !== ""
? `url(${backgroundImage}) ${backgroundPositionX} ${backgroundPositionY}`
: backgroundColor,
lineHeight: 1.4,
padding: "120px 50px 50px",
}}
>
<span
style={{
backgroundColor: titleBackgroundColor,
color: titleColor,
display: "inline",
padding: "0.5rem",
boxDecorationBreak: "clone",
}}
>
{title}
</span>
</h1>
);
}
Return to your Builder page and test out the new functionality for this registered component. When you add a background image to the input, you should see that background image replace the background color.
While the functionality of the registered component is working, the Options tab is a bit busy and confusing. When you are setting a background image, you should not need to also choose a background color.
To solve this, add the showIf
property to specific inputs you wish to hide or show depending on what other values are present within the component. This requires changes to the registered component definition, not the actual component.
The value to showIf
is a string, but it functions as a JavaScript expression. This expression is evaluated as true
or false
and determine whether or not the input should be displayed.
export const customHeaderInfo: RegisteredComponent = {
component: CustomHeader,
name: "CustomHeader",
inputs: [
{ name: "title", type: "text", defaultValue: "My Title" },
{ name: "titleColor", type: "color", defaultValue: "#FFFFFF" },
{ name: "titleBackgroundColor", type: "color", defaultValue: "#000000" },
{
name: "backgroundColor",
type: "color",
defaultValue: "#CCCCCC",
showIf: 'options.get("backgroundImage") === ""',
},
{ name: "backgroundImage", type: "url", defaultValue: "" },
{
name: "backgroundPositionX",
type: "text",
defaultValue: "100%",
showIf: 'options.get("backgroundImage") !== ""',
},
{
name: "backgroundPositionY",
type: "text",
defaultValue: "25%",
showIf: 'options.get("backgroundImage") !== ""',
},
],
};
In the example above, the following has changed:
- The
backgroundColor
,backgroundPositionX
, andbackgroundPositionY
inputs all have theshowIf
key with a string expression. - The
backgroundColor
input is only shown if the value of thebackgroundImage
input is an empty string. - Alternatively, the
backgroundPositionX
andbackgroundPositionY
inputs will only be shown if thebackgroundImage
input is not an empty string.
The video below shows a background image being added to the custom component. When the image URL is added, the background color input disappears and two new inputs appear related to the positioning of the background image.
Within each of the showIf
string values above, the options
object is used to gain access to the values of all inputs on the current registered component.
The .get()
method takes a string value that represents the name of the input. The value returned from the .get()
method is the current value of the input.
For more details on what objects are available to you within the expression, see the showIf
entry in Input types for custom components.
Visit Input types for custom components for more examples of what you can do with custom components and inputs. Or, see Child blocks in custom components to learn how to integrate Builder blocks into your custom components.