Content as a Service has revolutionized content management systems in the delivery of content. Content is created once, independent of channels, and delivered without additional custom application code. This saves a lot of time in the creation and maintenance of content and reduces the cost of operation.
Adobe Experience Manager (AEM) has out-of-the-box (OOTB) features like Content Services, Assets HTTP API, and Content Fragment. These features help marketers create, maintain, and publish content for multiple channels like web pages, mobile apps, IoT devices, screens, and many more.
For understanding the basics of Content Fragments, please do readWorking with Content Fragments.
The OOTB Content Fragment Data Types are basic widgets with specific UI behavior. For marketers, the basic behavior will not fulfill the authoring requirement. Thankfully, AEM is flexible so we can extend the UI behavior of the basic data types with ease to create new data types.
创建多选下拉
In this blog, I am going to extend the Enumeration data type to create a new Multi-Select Dropdown data type.
1. Overlay OOTB Enumeration Data Type
Overlay the OOTB Enumeration Data Type from libs (/libs/settings/dam/cfm/models/formbuilderconfig/datatypes/items) folder to apps (/apps/settings/dam/cfm/models/formbuilderconfig/datatypes/items) folder. See the below image:
2. Customize the Enumeration
After overlaying the OOTB node, change the node name to enumerationmultiselect. Along with the default attributes present on the node, addtagsfieldvalue in fieldProperties. Tagsfield points to the OOTB /libs/dam/cfm/models/editor/components/datatypeproperties/tagsfields/tagsfields.jsp data type which provide multiple select behavior. See the below image:
3.添加Custom Behavior
以下步骤添加自定义HTML背包ed DOM element which will be used to read and save the selected values in the multiselect. To achieve this overlay /libs/dam/cfm/models/editor/components/datatypeproperties folder to /apps as shown in the below image:
Create a JSP file uniqueidfield.jsp, below uniqueidfield folder, and add below code snippet. The below code creates the hidden element to the HTML DOM element:
<%@ page import="org.apache.sling.api.resource.ValueMap" %> <% %><%@include file="/libs/granite/ui/global.jsp" %><% %><%@ page session="false" contentType="text/html" pageEncoding="utf-8"%><% ValueMap fieldProperties = resource.adaptTo(ValueMap.class); String key = resource.getName(); String xssKey = xssAPI.encodeForHTMLAttr(key); %>
Add the newly created datatype property to the enumerationmultiselect node in fieldProperties attribute as shown below image:
4. Save Selected Values
By default, the values selected in the multi-select value will not be saved to the fragment. To achieve this, we need to add custom JavaScript code. In your custom application code, under the clientlibrary folder, add a new folder clientlib-author and add category dam.cfm.authoring.contenteditor.v2 as shown in the below image:
Create a new JS file named enumerationmultiselect.js add it to the js.txt file under the clientlib-author folder. Add the below code snippet to the JS file:
(function ($) { 'use strict'; var CFM, MASTER = "master", CFM_EDITOR_SEL = ".content-fragment-editor"; $( window ).load(function() { if (window.Dam != undefined) { CFM = window.Dam.CFM; getEnumerationContent(); var url = window.location.pathname; if(url.indexOf("/metadata-editor.html/") < 0) { extendRequestSave(); } } }); function getEnumerationContent() { if (CFM.EditSession != undefined) { var url = CFM.EditSession.fragment.urlBase + "/jcr:content/data.2.json"; $.ajax(url).done(loadContentIntoEnumerationContentField); } } function loadContentIntoEnumerationContentField(data) { var coralSelect = $('#aem-cfm-editor-elements-form .enumeration-multi-select'); $.each(coralSelect, function() { var name = $(this).attr('name'); var selectValue = data.master[name].split(','); setSelectValue($(this), selectValue); var tagList = getTagList(selectValue); $(this).find('.coral3-Select-tagList').append(tagList); }); } function setSelectValue(eachSelect, selectValue) { var selectedItem = $(eachSelect).find('coral-select-item'); $.each(selectedItem, function() { var value = $(this).attr('value'); if (selectValue.includes(value)) { $(this).attr('selected', ""); } }); } function getTagList(selectValue) { var html = ""; $.each(selectValue, function(index, value) { html = html + "" + value + " "; }); return html; } function getVariation() { var variation = $(CFM_EDITOR_SEL).data('variation'); variation = variation || "master"; return variation; } function getFormData() { var coralSelect = $('#aem-cfm-editor-elements-form .enumeration-multi-select'); var value = {}; $.each(coralSelect, function() { var tags = $(this).find('.coral3-Select-tagList .coral3-Tag'); var name = $(this).attr('name'); var values = []; $.each(tags, function() { var tagValue = $(this).val(); values.push(tagValue); }); value[name] = values.join(); }); return value; } function extendRequestSave(){ if (CFM.editor != undefined) { var originFn = CFM.editor.Page.requestSave; CFM.editor.Page.requestSave = requestSave; function requestSave(callback, options) { originFn.call(this, callback, options); var formData = getFormData(); if(formData.length == 0){ return; } var url = CFM.EditSession.fragment.urlBase + ".cfm.content.json", variation = getVariation(), createNewVersion = (options && !!options.newVersion) || false; formData[":type"] = "multiple"; formData[":newVersion"] = createNewVersion; formData["_charset_"] = "utf-8"; if(variation !== MASTER){ formData[":variation"] = variation; } var request = { url: url, method: "post", dataType: "json", data: formData, cache: false }; CFM.RequestManager.schedule({ request: request, type: CFM.RequestManager.REQ_BLOCKING, condition: CFM.RequestManager.COND_EDITSESSION, ui: (options && options.ui) }) } } } }(jQuery));
Create A Content Fragment Model
Now time to validate. Navigate to the Content Fragment Model console and you will see the new Enumeration Multi Select Data Type as showing in the below image:
Create a simple model by adding the drag and dropping the new Enumeration Multi Select Data Type and then click Save. With the new content fragment model, create a content fragment. We can then select multiple values from the enumeration.
The below video shows the behavior of the new Enumeration Multi-Select behavior on the content fragment.
For more information on this topic and related items, you can also read the below blogs. The below blogs will provide more ideas to customize content fragment model data types: