Goal
Adobe Experience Manager 2022.6.7904.20220629T070041Z-220600
For multiple configurable composite multifields in content fragments editor check this post
Create a Composite Multifield for Content Fragments Editor. Authors can edit the configuration of the multifield adding new fields or remove existing...
Demo | Package Install | CF Model | Github
Configure Composite MF
Multifield in Editor
Data Saved in CRX
Solution
1) Create the project eaem-cf-composite-mf
mvn -B org.apache.maven.plugins:maven-archetype-plugin:3.2.1:generate -D archetypeGroupId=com.adobe.aem
-D archetypeArtifactId=aem-project-archetype -D archetypeVersion=36 -D aemVersion=cloud
-D appTitle="Experience AEM CS CF Composite Multifield" -D appId="eaem-cf-composite-mf" -D groupId="apps.experienceaem.assets"
-D frontendModule=none -D includeExamples=n -D includeDispatcherConfig=n
2) Create a helper thirdparty loadash client library /apps/eaem-cf-composite-mf/lodash with property categories="[eaem.lodash]"
3) For the keyValues composite multifield create a clientlib /apps/eaem-cf-composite-mf/clientlib-mf with categories="[dam.cfm.authoring.contenteditor.v2]" and dependencies="[eaem.lodash]". Add the following code..
(function ($) {
const URL = document.location.pathname,
CFFW = ".coral-Form-fieldwrapper",
MASTER = "master",
CFM_EDITOR_SEL = ".content-fragment-editor",
KV_MF_SELECTOR = "[data-granite-coral-multifield-name='keyValues']";
let initialized = false;
if( !isCFEditor() ){
return;
}
init();
function init(){
if(initialized){
return;
}
initialized = true;
window.Dam.CFM.Core.registerReadyHandler(() => {
extendRequestSave();
hideTabHeaders();
addKeyValueMultiFieldListener();
Dam.CFM.editor.UI.addBeforeApplyHandler( () => {
Dam.CFM.EditSession.notifyActiveSession();
Dam.CFM.EditSession.setDirty(true);
});
});
}
function hideTabHeaders(){
$("coral-tablist").last().hide();
}
function addKeyValueMultiFieldListener(){
const $kvMulti = $(KV_MF_SELECTOR);
createTemplateFromLastParkedTab();
Coral.commons.ready($kvMulti[0], splitKeyValueJSONIntoFields);
}
function splitKeyValueJSONIntoFields(kvMFField){
const $kvMFField = $(kvMFField),
kvMFName = $kvMFField.attr("data-granite-coral-multifield-name");
_.each(kvMFField.items.getAll(), function(item) {
const $content = $(item).find("coral-multifield-item-content");
let jsonData = $content.find("[name=" + kvMFName + "]").val();
if(!jsonData){
return;
}
jsonData = JSON.parse(jsonData);
$content.html(getParkedMFHtml());
fillMultiFieldItem(item, jsonData);
});
}
function fillMultiFieldItem(mfItem, jsonData){
_.each(jsonData, function(fValue, fKey){
const field = mfItem.querySelector("[name='" + fKey + "']");
if(field == null){
return;
}
if(field.tagName === 'CORAL-DATEPICKER'){
field.valueAsDate = new Date(fValue);
}else{
field.value = fValue;
}
});
}
function createTemplateFromLastParkedTab(){
const $kvMulti = $(KV_MF_SELECTOR);
$kvMulti.find("template").remove();
let template = '<template coral-multifield-template=""><div>' + getParkedMFHtml() + '</div></template>';
$kvMulti.append(template);
}
function getParkedMFHtml(){
return $("coral-panel").last().find("coral-panel-content").html();
}
function getKeyValueData(){
const $kvMulti = $(KV_MF_SELECTOR),
kvMFName = $kvMulti.attr("data-granite-coral-multifield-name");
let kevValueData = [];
_.each($kvMulti[0].items.getAll(), function(item) {
const $fields = $(item.content).find("[name]"),
data = {};
_.each($fields, function(field){
if(canBeSkipped(field)){
return;
}
data[field.getAttribute("name")] = field.value;
});
kevValueData.push(JSON.stringify(data));
});
return { [ kvMFName] : kevValueData} ;
}
function canBeSkipped(field){
return (($(field).attr("type") == "hidden") || $(field).closest(CFFW).is(":hidden") ||!field.value);
}
function extendRequestSave(){
const CFM = window.Dam.CFM,
orignFn = CFM.editor.Page.requestSave;
CFM.editor.Page.requestSave = requestSave;
function requestSave(callback, options) {
orignFn.call(this, callback, options);
const kvData = getKeyValueData();
if(_.isEmpty(kvData)){
return;
}
const url = CFM.EditSession.fragment.urlBase + ".cfm.content.json",
variation = getVariation(),
createNewVersion = (options && !!options.newVersion) || false;
let data = {
":type": "multiple",
":newVersion": createNewVersion,
"_charset_": "utf-8"
};
if(variation !== MASTER){
data[":variation"] = variation;
}
const request = {
url: url,
method: "post",
dataType: "json",
data: _.merge(data, kvData),
cache: false
};
CFM.RequestManager.schedule({
request: request,
type: CFM.RequestManager.REQ_BLOCKING,
condition: CFM.RequestManager.COND_EDITSESSION,
ui: (options && options.ui)
})
}
}
function getVariation(){
var variation = $(CFM_EDITOR_SEL).data('variation');
variation = variation || "master";
return variation;
}
function isCFEditor(){
return ((URL.indexOf("/editor.html") == 0)
|| (URL.indexOf("/mnt/overlay/dam/cfm/admin/content/v2/fragment-editor.html") == 0) )
}
}(jQuery));
hi srrekant , its not working if i have two multifiled with diifrent name in a single cf , how to fix this ?
ReplyDeletehttps://experience-aem.blogspot.com/2023/06/aem-cloud-service-multiple-composite-multifields-in-content-fragment-editor.html
DeleteHi Sreekanth,
ReplyDeletewe have preview button for content fragment in Adobe Cloud Service . Can we implement same feature for on premises .
The Feature is detailed in this doc.
https://experienceleague.adobe.com/docs/experience-manager-learn/getting-started-with-aem-headless/how-to/preview.html?lang=en
Thanks
Hi Sreekanth,
ReplyDeleteI am having an issue when I refresh the content fragment multiple times (2-3 times), then check the crxde data, composite multifield json gets wiped. Any fix for it?