Salesforce Commerce Cloud - Drag-and-drop support in page designer
As I’ve shared in some previous posts, I am currently working on a React application that uses Salesforce Commerce Cloud as a quasi-headless CMS. We’re using Page Designer to provide our React app with a JSON representation of our pages set up in the Page Designer GUI.
Sadly with this approach, we’ve lost a powerful feature of Page Designer, that being the drag-and-drop / click to edit features. However, this turned out to be merely an implementation issue, and is very salvageable with some minor, quite straight forward changes.
That being said, I am not aware of any documentation around this drag-and-drop behavior, and the following is purely based on my experience, digging through the SFRA pages in Page Designer, coupled with a lot of trial and error. Tread carefully…
Some sample data
I’ve found to get this working again we need a few new HTML data attributes on our components and regions we have this working again. Let’s walk through the required code, using this sample serialized page structure as an example:
You can see the above is a JSON tree representation of a page with the ID of homepage
, in which
we have a single region (body
) and inside that we have added a component called columns
.
In that component we have two more left
and right
, with each column containing a textbox
component.
What we’re after is to be able to click on each text box and open up the relevant attribute editor
panel, and for Page Designer to allow us to drag-and-drop these, and other, components into the
regions we’ve got in this page structure, these include body
, left
, and right
.
Components
To start off we’re going to work with our components to get our click-to-edit behavior working. Around each component we need to add the following data attributes to enable the click to edit and other annotations within the page designer tool.
The first three: data-allow-select
, data-allow-move
, data-allow-delete
are relatively
self-explanatory, and simply enable/disable the selection, movement, or deletion of the component
they’re applied to.
Things start to get interesting with data-item-id
. This is a combination of the word component
,
a pipe character and then the ID of the component, as supplied in the serialized page structure.
For example our textbox
component from the right column in the above example would the following
value:
component|230e41aa858be42df3357510db
This attribute seems to act as some kind of unique identifier so page designer can map these to the appropriate component entries in the Page Designer GUI.
The last attribute we need to add is data-sfcc-pd-component-info
which seems to be a stringify’d
JSON object with additional information about the component. Here is a more complete example
implemented in React:
With this we now have the component annotations back, along with the click-to-edit behavior! Take a look:
Above shows our Columns
component in action featuring our new component data attributes. As we
hover on the component note its name showing up in the little tab at the top of the component, and
the move icon, alongside the delete button.
Regions
For any components that implement sub-regions, we will need to wrap these elements with the following data attributes so the Page Designer GUI can correctly identify them, similar to what we did with our components.
The data-allow-drop
property here seems to control if users will be able
to drop new components in the region.
The data-item-id
features a rather important difference compared to our components.
In order to properly support nested regions (sub-regions) we need to know the ID of
the parent component of the region. Using our sample JSON from above, and looking at the columns
component, and it’s Left
region. The region’s data-item-id
would look like this:
This use of the parent component ID is a vital bit of logic to ensure Page Designer can keep track of the components and their regions when moving components around, without it, the drag-and-drop feature will not work.
The final attribute is data-sfcc-pd-region-info
, and similar to what we did for our components,
this involves a stringify’d JSON object with additional information about the region.
Putting that all together into a React component to annotate a region:
Only show these annotations in Page Designer
These attributes have zero impact in the final application we serve to our customers. But it can pollute the page with a lot of unnecessary markup especially if your pages are made up of a lot of components.
Ideally we only render these annotations when we’re in “edit mode” or within the Page Designer tool. Sadly there isn’t a great way to tell if you’re in a Page Designer session or not other than URL sniffing, which you can do by using the following snippet taken from SFRA:
Having this to our React application we can conditionally include (or through a higher order component) each Page Designer component and region to ensure we don’t expose this unnecessary bloat to the user. Another option could be to have a separate React build for use on Page Designer vs production if you are really worried about bundle size or leaking low-level implementation details.
We’re done
A few data attributes and some light ancestry, and we’re back in business with drag-and-drop support in Page designer for our a React app using Salesforce Commerce Cloud as a headless CMS.
Hope this helped! This post is part of my #sfcc-with-react series where I look at how to make use of SFCC in React.