Creating a Breakout Custom Attribute Editor in Page Designer for Salesforce Commerce Cloud
Salesforce commerce cloud
{
"id": "customCarEditor",
"name": "Custom Car Editor",
"type": "custom",
"required": false,
"editor_definition": {
"type": "com.sfcc.customCarEditorTrigger",
"configuration": {
"options": {
"config": [
"Yugo",
"Mercedes",
"BMW",
"Seat"
]
}
}
}
}
{
"name": "Car Custom Editor",
"description": "Custom editor with car picker breakout functionality!",
"resources": {
"scripts": [
"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.0/jquery.min.js",
"/experience/editors/com/sfcc/customCarEditorTriggerScript.js"
],
"styles": [ "https://cdnjs.cloudflare.com/ajax/libs/design-system/2.8.3/styles/salesforce-lightning-design-system.min.css",
"/experience/editors/com/sfcc/customCarEditorTriggerCSS.css"
]
}
}
'use strict';
var HashMap = require('dw/util/HashMap');
var Resource = require('dw/web/Resource');
var PageMgr = require('dw/experience/PageMgr');
module.exports.init = function (editor) {
// Default values properties
var defaults = {
buttonBreakout: 'Select',
titleBreakout: 'Cars',
placeholder: 'Select your custom car',
description: 'Description of Custom Car Editor',
group1: 'car group1 configuration'
};
// Add some localizations
var localization = Object.keys(defaults).reduce(function (acc, key) {
acc.put(key, Resource.msg(key, 'experience.editors.com.sfcc.customCarEditorTrigger', defaults[key]));
return acc;
}, new HashMap());
editor.configuration.put('localization', localization);
// Pass through property `options.config` from the `attribute_definition` to be used in a breakout editor
var options = new HashMap();
options.put('config', editor.configuration.options.config);
// Create a configuration for a custom editor to be displayed in a modal breakout dialog (breakout editor)
var breakoutEditorConfig = new HashMap();
breakoutEditorConfig.put('localization', localization);
breakoutEditorConfig.put('options', options);
// Add a dependency to the configured breakout editor
var breakoutEditor = PageMgr.getCustomEditor('com.sfcc.customCarEditorBreakout', breakoutEditorConfig);
editor.dependencies.put('customCarEditorBreakoutScript', breakoutEditor);
};
{
"name": "Custom Car Editor Breakout",
"description": "An car editor with breakout functionality",
"resources": {
"scripts": [
"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.0/jquery.min.js",
"/experience/editors/com/sfcc/customCarEditorBreakoutScript.js"
],
"styles":[
"https://cdnjs.cloudflare.com/ajax/libs/design-system/2.9.4/styles/salesforce-lightning-design-system.min.css",
"/experience/editors/com/sfcc/customCarEditorBreakoutCSS.css"
]
}
}
// This is optional file where config can also be initialized
("use strict");
var URLUtils = require("dw/web/URLUtils");
module.exports.init = function (editor) {
var optionsConfig = editor.configuration.options.config;
// Car values can be set here
var optionsInit = [];
// Init editor configuration
editor.configuration.options.put("init", optionsInit);
// Provide `baseUrl` to the static assets/content
editor.configuration.put(
"baseUrl",
URLUtils.staticURL("/experience/editors/com/sfcc/").https().toString()
);
};
// Code in the client-side JavaScript file for the trigger editor
(() => {
let resultEl;
subscribe(
"sfcc:ready",
async ({
value,
config,
isDisabled,
isRequired,
dataLocale,
displayLocale,
}) => {
({ localization = {} } = config);
const template = document.createElement("template");
template.innerHTML = `
<div>
<p>Pick a custom car</p>
<button id='breakout-trigger'>Click</button>
<p id='result'></p>
</div>`;
const clone = document.importNode(template.content, true);
document.body.appendChild(clone);
resultEl = $("#result");
var openButtonEl = $("#breakout-trigger");
openButtonEl.on("click", handleBreakoutOpen);
resultEl.text(obtainDisplayValue(value));
}
);
function obtainDisplayValue(value) {
return (
"Car picked: " +
(typeof value === "object" &&
value != null &&
typeof value.value === "string"
? value.value
: "")
);
}
function handleBreakoutOpen() {
const { titleBreakout } = localization;
emit(
{
type: "sfcc:breakout",
payload: {
id: "customCarEditorBreakoutScript",
title: titleBreakout,
},
},
handleBreakoutClose
);
}
function handleBreakoutClose({ type, value }) {
// Now the "value" can be passed back to Page Designer
if (type === "sfcc:breakoutApply") {
handleBreakoutApply(value);
} else {
handleBreakoutCancel();
}
}
function handleBreakoutCancel() {
// left empty in case you want to do more customization on this event
}
function handleBreakoutApply(value) {
// Emit value update to Page Designer host application
resultEl.text(obtainDisplayValue(value));
emit({
type: "sfcc:value",
payload: value,
});
}
})();
// Code in the client-side JavaScript file for the breakout editor
(() => {
let options;
let carsEl;
subscribe('sfcc:ready', async ({ value, config, isDisabled, isRequired, dataLocale, displayLocale }) => {
// Once the breakout editor is ready, the custom code is able to select or
// Create a value. Any meaningful change to a value/selection needs to be
// reflected back into the host container via a `sfcc:value` event.
const template = document.createElement('template');
template.innerHTML = `<div class="cars"></div>`;
const clone = document.importNode(template.content, true);
document.body.appendChild(clone);
({ options = {} } = config);
carsEl = document.querySelector('.cars');
options.config.forEach(appendItems());
});
function appendItems() {
return option => {
const itemTemplate = createNewCarTemplate(option);
const itemEl = document.importNode(itemTemplate.content, true);
const linkEl = itemEl.querySelector('p');
linkEl.addEventListener('click', handleSelect);
carsEl.appendChild(itemEl);
};
}
function createNewCarTemplate(carName) {
const template = document.createElement('template');
template.innerHTML = `<p>${carName}</p>`.trim();
return template;
}
function handleSelect({ target }) {
// The value changed and the breakout editor's host is informed about the
// value update via a `sfcc:value` event.
const selectedCar = target.innerText;
emit({
type: 'sfcc:value',
payload: selectedCar ? { value: selectedCar } : null
});
}
})();
)



