The Builder Visual Editor helps you add event handlers, bind to state, and even add custom JavaScript that runs on your page.
Tip: To add custom HTML to your Page or Section, use the Custom Code Block rather than custom JavaScript.
In Builder, you can bind state values to Builder blocks and implement custom actions when users interact with your content.
For detailed instructions on incorporating state bindings or action handlers, visit Building Interactivity Using State and Actions.
When adding custom JavaScript code within a state binding or action handler, remember that you don't need to use the return
keyword to yield a value. Instead, choose from these four examples:
For straightforward, one-line expressions, you can write code directly in the code editor without the return
statement:
state.showWelcomeMessage ? 'Say Hello' : 'Say Goodbye'
For more intricate logic, export a default value:
let greeting;
if (justLoggedIn) {
value = 'Welcome';
} else {
value = 'hi';
}
export default greeting;
You can access Builder state in both state bindings and action handlers. While state bindings are typically closely bound to Builder, you can also modify the state value within the binding. For example:
// use the plain value from state
state.someStringValue
// uppercase the state value
state.someStringValue.toUpperCase()
// return a different value depending on state property
state.someBooleanValue ? 'yes' : 'no
Action handlers introduce an additional object you can access: event
.
This event
object represents the HTML event triggered by the selected action. You can leverage event
to access the event's target element or invoke methods such as preventDefault
or stopPropagation
:
// access the value attribute (ie from an input)
// and store it in builder state
state.someStateProp = event.currentTarget.value;
// if you have a link with an href, you might want to stop
// default browser navigation and handle this yourself
event.preventDefault();
var targetElementId = event.currentTarget.id;
var elementToScrollTo = document.getElementById(targetElementId);
elementToScrollTo.scrollIntoView({ behavior: 'smooth' });
To add custom styles or JavaScript to your content:
- In the content entry, go to the Data tab.
- Expand the Code section.
- Click the Edit Custom JS + CSS button.
- In the window that opens, you can put your CSS on the left and your JavaScript on the right.
This example shows adding some custom CSS to a Page and then applying it to elements on the Page.
The CSS in below—which the video features–applies a margin and blue color to links (the a
tag), and a yellow background color to any element with .my-class
:
/* Style all link elements */
a {
margin: 10px;
color: blue;
}
/* Style all elements with the class name "my-class" */
.my-class {
background-color: yellow;
}
To use the CSS, add the code to the Custom Code editor and then apply the styles either by applying a class to an element or creating elements that would naturally inherit those styles.
The following video shows how to add custom CSS and apply it to elements. A written explanation follows the video.
Any element that has the .my-class
applied inherits the .my-class
styles as soon as .my-class
is applied to that element. In this example, when the Box is given the class .my-class
, its background immediately turns yellow.
Any elements that are styled directly in the CSS, such as links in this example, are styled automatically. This happens in the video as soon as the copy becomes a link.
You can run JS client side as well as server side using Builder.isBrowser
and Builder.isServer
. By default, any code not wrapped with Builder.isBrowser
or Builder.isServer
is run on Builder's servers.
To run code client-side, wrap it in if (Builder.isBrowser) {}
.
For example, suppose you're rendering your Builder content lazily on the client and you want to support linking directly to certain sections of a page based on the ID attribute of the section. You could do this with some custom JavaScript:
if (Builder.isBrowser) {
const el = location.hash &&
document.getElementById(location.hash.slice(1))
el.scrollIntoView({ behavior: 'smooth' });
}
You also have access to fetch()
on the client and server. For server side data, you can export a default promise that resolves with the necessary data before responding:
async function main() {
if (Builder.isServer) {
// Place any code here you want to only run on
// the server. Any data fetched on the server
// will be available to re-hydrate on the client
// if added to the state object
await fetch(someUrl)
.then(res => res.json())
.then(data => {
// set the data on the state object so
// you can access it from your components
state.someData = data;
});
}
if (Builder.isBrowser) {
// Place code that you only want to run
// in the browser (client-side only) here
// For example, anything that uses
// document/window access or DOM manipulation
}
}
export default main();
In the provided example, data fetched on the server is stored on the state
object and can be accessed as data bindings in both the server and client UIs. For more details on fetching and using data, refer to Dynamic Preview URLs.
Remember to exercise caution and consider the impact on performance and security when adding custom code to your site. For instance, when incorporating custom event listeners, ensure the use of passive events for proper handling.
When adding your custom JavaScript code, the useful builder
values include:
Builder.isServer
: Use to determine if the code is running on the server-side (such as in a Node.js environment) or not. It returnstrue
if the code is executing on the server, andfalse
if it's running in a browser.Builder.isBrowser
: Use to check if the code is running in a browser environment. It returnstrue
if the code is executing in a web browser, andfalse
otherwise, including server-side.Builder.isPreviewing
: Use to check if the code is currently in preview mode within the Visual Editor. It returnstrue
if the code is being previewed in the Visual Editor, and false if it's not in preview mode.Builder.isEditing
: Use to check if the code is currently being edited within the Builder.io editor. It returnstrue
if the code is being edited, and false if it's not being edited.
For the source code, visit GitHub.
Tip: If your custom code isn't delivering expected results when working with page elements or third-party scripts, the event loop's asynchronous nature might be the reason. Consider using setTimeout()
or conditional checks to time your code accurately and synchronize it with the page's rendering process.
For more information on the global objects available, visit:
Up next
3rd party libraries