Sign up: Build components with Figma and AI

Announcing Visual Copilot - Figma to production in half the time

Builder.io
Builder.io
Contact sales

Sign up: Build components with Figma and AI

Announcing Visual Copilot - Figma to production in half the time

The Data tab in the Visual Editor helps you add event handlers, bind to state, and 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 the Data tab, you can bind state values to Builder blocks and implement custom actions when users interact with content. For more information, see Building Interactivity Using State and Actions.

When adding custom JavaScript code within a state binding or action handler, the return keyword is not needed to yield a value.

For one-line expressions, write code directly in the code editor without the return statement:

state.showWelcomeMessage ? 'Say Hello' : 'Say Goodbye'

For complex logic, export a default value:

const greeting = isLoggedIn ? 'Welcome' : 'hi';
export default greeting;

Builder state is accessible in both state bindings and action handlers. State bindings typically bind closely to Builder, but you can also modify the state value within the binding:

// 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 provide an additional object called event to represent the HTML events the selected action triggers. Use event to access the event's target element or invoke methods such as preventDefault or stopPropagation:

// access the value attribute (for example, from an input)
// and store in builder state
state.someStateProp = event.currentTarget.value;

// for links with an href, stop default browser navigation 
// and handle this with custom logic
event.preventDefault();
var targetElementId = event.currentTarget.id;
var elementToScrollTo = document.getElementById(targetElementId);
elementToScrollTo.scrollIntoView({ behavior: 'smooth' });

The video below shows accessing state bindings and custom code options in the Visual Editor's Data tab:

To add custom styles or JavaScript to content:

  1. In the Visual Editor, go to the Data tab.
  2. In the Code section, click Edit Content JS + CSS.
  3. In the window that opens, customize CSS and JavaScript behavior.

The video below shows how to access the Edit Content JS + CSS button in the Data tab:

You can add custom CSS code from the Data tab and apply the CSS styles to elements and blocks within that Page.

In the example below, the CSS applies a margin and blue color to all the a tags, 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;
}

Any element that has .my-class applied inherits the .my-class styles as soon as .my-class is applied to that element. In this example, the background immediately turns yellow when the Box receives the class .my-class.

Elements with direct styling in the CSS, such as links in this example, receive styling automatically.

The video below shows how to add custom CSS and apply styles to elements:

JavaScript can run client-side and server-side using Builder.isBrowser and Builder.isServer. The editor provides access to global objects, including state, context, fetch, and Builder.

By default, any code not wrapped with Builder.isBrowser or Builder.isServer runs on Builder's servers. To run code client-side, wrap code in if (Builder.isBrowser) {}.

When writing custom JavaScript, you have access to these global objects:

ObjectDescription

state

manages application state and data bindings

context

accesses passed-down data and functions

fetch

makes HTTP requests to external services

Builder

The Builder object provides these useful properties:

  • Builder.isServer returns true if code executes on the server, false in browser.
  • Builder.isBrowser returns true if code executes in browser, false on server-side.
  • Builder.isPreviewing returns true when in Visual Editor preview mode.
  • Builder.isEditing returns true when editing in the Visual Editor.

For example, to enable smooth scrolling to page sections based on URL hash fragments:

if (Builder.isBrowser) {
    const el = location.hash &&
      document.getElementById(location.hash.slice(1))

    el.scrollIntoView({ behavior: 'smooth' });
}

Access to fetch() exists on both client and server. For server-side data, export a default promise that resolves with the necessary data before responding:

async function main() {
  if (Builder.isServer) {
    // Place any code here to only run on
    // the server. Any data fetched on the server
    // is available to re-hydrate on the client
    // when added to the state object
    await fetch(someUrl)
      .then(res => res.json())
      .then(data => {
        // set the data on the state object so
        // components can access the data
        state.someData = data;
     });
  }
  if (Builder.isBrowser) {
    // Place code to only run
    // in the browser (client-side only) here
    // For example, anything that uses
    // document or window access or DOM manipulation
  }
}

export default main();

In the server-side 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 interfaces. For more details on fetching and using data, refer to Dynamic Preview URLs.

When adding custom code, consider the impact on performance and security. When using custom event listeners, use passive events to avoid blocking the main JS thread.

When working with page elements or third-party scripts, use setTimeout() or conditional checks to delay code execution until DOM elements are ready to avoid reference errors.

Custom code execution requires the 'unsafe-eval' directive in Content Security Policy headers when using complex JavaScript expressions. For more information, see Content Security Policy: need for unsafe-eval.

To learn more about Builder's data handling and customization features:

Up next

3rd party libraries

Was this article helpful?

Product

Visual CMS

Theme Studio for Shopify

Sign up

Login

Featured Integrations

React

Angular

Next.js

Gatsby

Get In Touch

Chat With Us

Twitter

Linkedin

Careers

© 2020 Builder.io, Inc.

Security

Privacy Policy

Terms of Service

Get the latest from Builder.io

By submitting, you agree to our Privacy Policy

  • Fusion

  • Publish

  • Product Updates

  • Figma to Code Guide

  • Headless CMS Guide

  • Headless Commerce Guide

  • Composable DXP Guide

Security

Privacy Policy

SaaS Terms

Trust Center

Cookie Preferences