Force Selection für Tags Field
Freilegen von versteckten Features im CFM Editor von AEM - Teil 2
Mit dem Tag-Feld innerhalb der AEM Content Fragment Models (CFMs) können Sie Tags als Content zu Content Fragments (CFs) hinzufügen. Dies ist eine sehr hilfreiche Funktion zur Wiederverwendung der leistungsstarken AEM-Tag-Funktionalität, nicht nur als Metadaten sondern auch innerhalb des Contents.
Aber das Feld hat einen großen Nachteil: Der Autor kann wie bei einem Freitext Feld eigene Tags eingeben und On-The-Fly erstellen. Diese Tags sind dann in einem Standard-Namespace und nicht in Ihrer gut durchdachten Tag-Struktur gespeichert.
Hinzufügen der force selection Funktionalität
Wir müssen uns also eine Lösung überlegen, wie wir den Autor forcieren können, nur die bereits erstellten Tags auszuwählen, um ein Chaos in unseren Tags zu vermeiden. Und hier kann ein wenig AEM Reverse Engineering sehr hilfreich sein.
Werfen wir einen Blick auf die Komponente, die AEM für dieses Tag-Feld verwendet. Sie finden die CFM-Komponenten unter diesem Pfad:
- /libs/settings/dam/cfm/models/formbuilderconfig/datatypes/items
Und hier sehen wir nun, dass das Tag-Feld diesen resourceType hat:
- /libs/cq/gui/components/coral/common/form/tagfield
Jetzt können wir uns die Implementierung anschauen in der render.jsp von genau diesem resourceType:
Ist das nicht genau das, wonach wir suchen? 🥳
Toll - aber wie können wir das jetzt in unserem Content Fragment Model verwenden? Dazu müssen wir etwas mehr reverse engineering betreiben.
Schauen wir uns noch einmal das CFM-Tag-Feld an und schauen, wie es zusammengesetzt ist. Dazu können wir einen Blick auf die fieldProperties werfen unter
- /libs/settings/dam/cfm/models/formbuilderconfig/datatypes/items/tagfield/tagsfields.jsp (siehe Bild oben)
In der tagsfields.jsp können wir sehen, dass die Eigenschaft "forceSelection" bereits dauerhaft auf false gesetzt ist. Wir müssen diese Datei also überschreiben/überlagern (overide), um die Eigenschaft für den CFM-Autor sichtbar zu machen.
Dazu können Sie eine Datei "tagsfields.jsp" unter dem exakten Pfad, aber unter /apps erstellen:
- /apps/settings/dam/cfm/models/formbuilderconfig/datatypes/items/tagfield/tagsfields.jsp
Dadurch verwendet AEM unsere eigene Datei anstatt der unter /libs.
In diese Datei kopieren wir dann den Inhalt aus der Datei /libs und ändern ihn entsprechend:
Für copy pasting:
<%@ page import="org.apache.sling.api.resource.ValueMap" %><%
%><%@include file="/libs/granite/ui/global.jsp" %><%
%><%@ page session="false" contentType="text/html" pageEncoding="utf-8"
import="com.adobe.granite.ui.components.formbuilder.FormResourceManager,
org.apache.sling.api.resource.Resource,
org.apache.sling.api.resource.ValueMap,
java.util.HashMap"%><%
ValueMap fieldProperties = resource.adaptTo(ValueMap.class);
String key = resource.getName();
String xssKey = xssAPI.encodeForHTMLAttr(key);
%>
<input type="hidden" name="./content/items/<%= xssKey %>/multiple" value="false">
<input type="hidden" name="./content/items/<%= xssKey %>/cq:showOnCreate" value="true">
<input type="hidden" name="./content/items/<%= xssKey %>/autocreateTag" value="true">
<!-- BEGIN ORIGINAL FIELD -->
<!--<input type="hidden" name="./content/items/<%= xssKey %>/forceSelection" value="false">-->
<!-- END ORIGINAL FIELD -->
<!-- BEGIN CUSTOM CODE -->
<%
HashMap<String, Object> values = new HashMap<String, Object>();
values.put("granite:class", "checkbox-label forceSelection");
values.put("text", i18n.get("Force Selection"));
values.put("value", true);
values.put("uncheckedValue", false);
values.put("checked", Boolean.valueOf(fieldProperties.get("forceSelection", String.class)));
values.put("name", "./content/items/" + xssKey + "/forceSelection");
FormResourceManager formResourceManager = sling.getService(FormResourceManager.class);
Resource placeholderFieldResource = formResourceManager.getDefaultPropertyFieldResource(resource, values);
%><sling:include resource="<%= placeholderFieldResource %>" resourceType="granite/ui/components/coral/foundation/form/checkbox"/>
<!-- END CUSTOM CODE -->
Mit diesem benutzerdefinierten Code haben wir nun die forceSelection Property als Checkbox im CFM-Editor und der Benutzer kann nur die Tags auswählen, aber keine neuen erstellen.
Disclaimer
Bei der Erweiterung von AEM-Out-of-the-Box-Funktionen müssen wir uns immer fragen, ob es das Risiko wert ist, Dateien zu überschreiben (overwrite). Denn eine neue AEM-Version kann Änderungen an unseren geänderten Dateien enthalten und zu unvorhergesehenen Problemen führen, da es keine Möglichkeit gibt, zu wissen, was sich geändert hat, wenn man nicht direkt in die jsp/html/...-Dateien im Ordner /libs schaut.
In diesem Fall ist das Risiko relativ gering, da wir nur eine einzige kleine jsp-Datei ändern. Aber auch für diese jsp-Datei müssen wir sehen, ob und welche Änderungen bei jedem AEM-Upgrade vorgenommen wurden.
Getestet mit AEM 6.5.17
Mehr zur Erweiterung der Content Fragments Funktionalität finden Sie hier: