Skip to content

Instantly share code, notes, and snippets.

@kapunahelewong
Created July 28, 2022 20:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kapunahelewong/7f5af890697fa062beaee1df3e7fcaf6 to your computer and use it in GitHub Desktop.
Save kapunahelewong/7f5af890697fa062beaee1df3e7fcaf6 to your computer and use it in GitHub Desktop.
Builder Custom Component with Children
import React from 'react';
import ReactDOM from 'react-dom';
import { Switch, Route, BrowserRouter, Link } from 'react-router-dom';
import { BuilderComponent } from '@builder.io/react';
import { Builder, withChildren } from '@builder.io/react';
// for tabs
import { useState } from 'react';
import { BuilderBlocks } from '@builder.io/react';
import './index.css';
function App() {
return (
<BrowserRouter>
<header>
<div className="logo">MY SITE</div>
<div className="links">
<Link className="link" to="/">
Home
</Link>
<Link className="link" to="/about">
About
</Link>
<Link className="link" to="/page-1">
Page 1
</Link>
<Link className="link" to="/page-2">
Page 2
</Link>
<Link className="link" to="/404">
404
</Link>
</div>
</header>
<div className="App">
<Switch>
<Route path="/" exact component={Home} />
<Route path="/about" exact component={About} />
<Route render={({ location }) => <CatchallPage key={location.key} />} />
</Switch>
</div>
</BrowserRouter>
);
}
class CatchallPage extends React.Component {
state = { notFound: false };
render() {
return !this.state.notFound ? (
<BuilderComponent
apiKey="36b55672551d40f49426c8a2712817a6"
model="page"
contentLoaded={content => {
if (!content) {
this.setState({ notFound: true });
}
}}
>
<div className="loading">Loading...</div>
</BuilderComponent>
) : (
<NotFound /> // Your 404 content
);
}
}
const Home = () => <h1>I am the homepage!</h1>;
const About = () => <h1>I am the about page!</h1>;
const NotFound = () => <h1>No page found for this URL, did you publish it?</h1>;
const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);
export const Hero = props =>
<div>{props.children}</div>
const HeroWithBuilderChildren = withChildren(Hero)
Builder.registerComponent(HeroWithBuilderChildren, {
name: 'Hero',
// Adding defaults is important for easy usability
defaultChildren: [
{
'@type': '@builder.io/sdk:Element',
component: { name: 'Text', options: { text: 'I am child text block!' } }
}
]
})
// Tabs
// 2. Create your component.
// This is a tabs component with some basic styles. When the user clicks on a tab, that content becomes active.
function Tabs(props) {
const [activeTab, setActiveTab] = useState(0);
return (
<>
<div
style={{
display: 'flex',
overflow: 'auto',
}}
>
{props.tabs?.map((item, index) => (
<span
key={index}
style={{
padding: 20,
color: activeTab === index ? 'blue' : '#000',
}}
onClick={() => {
setActiveTab(index);
}}
>
{item.label}
</span>
))}
</div>
{/* // This section tells BuilderBlocks what to expect:
// the parent id, the path to the child component,
// and what the blocks should be made of.
// Here, the blocks are made of the content of the active tab */}
{props.tabs?.length && (
<BuilderBlocks
parentElementId={props.builderBlock.id}
dataPath={`component.options.tabs.${activeTab}.content`}
blocks={props.tabs[activeTab].content}
/>
)}
</>
);
}
// Register your component. This component is called Tabs, is of type list and contains two subFields as children: a label and the content.
// As a best practice, provide a defaultValue. The default label is "Tab 1" and the content is an empty array.
Builder.registerComponent(Tabs, {
name: 'Tabs',
inputs: [
{
name: 'tabs',
type: 'list',
subFields: [
{
name: 'label',
type: 'text',
defaultValue: 'New tab',
},
{
name: 'content',
type: 'uiBlocks',
defaultValue: [],
},
],
defaultValue: [
{
label: 'Tab 1',
content: [],
},
],
},
],
});
const Heading = props => (
<h1>{props.title}</h1>
)
Builder.registerComponent(Heading, {
name: 'Heading',
hideFromInsertMenu: true,
inputs: [{
name: 'title',
type: 'text',
defaultValue: 'I\'m version 1' }]
})
Builder.registerComponent(Heading, {
name: 'Heading',
inputs: [{
name: 'title',
type: 'text',
defaultValue: 'I\'m version 2' }]
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment