Visual Data Bindings are deprecated.
Visual Data Bindings have been deprecated since October 2025. CloudCannon continues to maintain them and fix critical bugs, but they receive no new features or further development. Existing Sites relying on this configuration will keep working. For new Sites, we recommend Editable Regions.
Visual Data Bindings use HTML attributes to tell CloudCannon which element on your page corresponds to which piece of data, allowing you to click on and edit data in the Visual Editor CloudCannon's visual editing interface provides a user-friendly way of updating your website files on an interactive preview of your webpage. You can navigate around your website preview using links/buttons, as you would on the live version, and edit your content inline on the page, or with the data panel or sidebar. What you see in the Visual Editor is what your website visitors will see on your live webpages.Visual Editor
React passes CloudCannon's visual editing interface provides a user-friendly way of updating your website files on an interactive preview of your webpage. You can navigate around your website preview using links/buttons, as you would on the live version, and edit your content inline on the page, or with the data panel or sidebar. What you see in the Visual Editor is what your website visitors will see on your live webpages.data- attributes straight through to the DOM, so adding data-cms-bind to an element works the same as it does in plain HTML.CloudCannon draws the same editing overlays over it in the Visual EditorVisual Editor
The part React adds is threading the path. A binding names a value's full path from the root of your data, but a reusable component has no way of knowing where in that structure it has been placed. The component above it does, so pass the path down as a prop.
Visual Data Bindings cannot re-render the value once you change the data behind them. For that, please read our documentation on using Visual Data Previews with React.
Pass binding paths through components#
Give each component a prop holding its own path, and build child bindings from it.
function Hero({ path, data }) {
const bind = (key) => [path, key].filter(Boolean).join('.');
return (
<section>
<h1 data-cms-bind={bind('title')}>{data.title}</h1>
<p data-cms-bind={bind('subtitle')}>{data.subtitle}</p>
</section>
);
}Joining with filter(Boolean) drops an empty path, so a component placed at the root produces title rather than .title.
The parent passes the path it occupies, and a component rendered at the root of your data passes an empty string.
<Hero path="hero" data={page.hero} />
<Hero path="" data={page} /> An empty path is a valid value to pass down, because bind() discards it when building child bindings.
Never render an empty binding#
An empty path is fine to pass as a prop, but it must never reach the DOM as an attribute. CloudCannon treats data-cms-bind="" as a binding it cannot resolve: the element still gets an overlay in the Visual Editor, bound to a field named unset that does not exist in your data.
Render the attribute only when the component has a path.
function Hero({ path, data }) {
const bind = (key) => [path, key].filter(Boolean).join('.');
return (
<section {...(path ? { 'data-cms-bind': path } : {})}>
<h1 data-cms-bind={bind('title')}>{data.title}</h1>
</section>
);
}Spreading a conditional object adds the attribute when path has a value and omits it entirely when path is empty.
Arrays#
Every binding you nest adds a click, because a child binding only becomes selectable once its parent is selected. Where you have an array component rendering an item component, binding both means two clicks to reach an item.
Bind the items and leave the array container unbound. The items keep their reordering and removal controls, and a Organization Member A person who belongs to the same Organization as you. Organization Members are other CloudCannon users who have been invited to your Organization to collaborate on Sites, edit content, or manage settings. Each Organization Member has their own CloudCannon account with individual permissions assigned through Permission Groups, and uses one Seat in your Subscription Plan. Organization Members were previously called Team Members.Organization Member