Date Range Validation Erweiterung
Freilegen von versteckten Features des CFM Editors von AEM - Teil 1
Haben Sie sich jemals gefragt, wie Sie sicherstellen können, dass zwei Datumsfelder innerhalb eines Content Fragments (CF) zusammen validiert werden können, um sicherzustellen, dass eines vor/nach dem anderen liegt?
Leider verfügen Content Fragment Models (CFMs) in AEM nicht über Validierungsregeln, die sich über mehrere Felder erstrecken, wie in AEM Forms.
Es gibt jedoch eine versteckte Funktionalität im Datepicker, die offengelegt werden kann, um eine Date-Range-Validierung zu ermöglichen.
Diese versteckte Funktionalität ist Teil des zugrundeliegenden Granite Datepicker, der für den Content Fragment Datepicker verwendet wird.
Aus der Dokumentation:
- beforeSelector
- Specifies a CSS selector targeting another datepickers that are before this datepicker. If those datepickers are not before this datepicker, it will be invalid.
- afterSelector
- Specifies a CSS selector targeting another datepickers that are after this datepicker. If those datepickers are not after this datepicker, it will be invalid.
Erster Schritt: Hinzufügen des Property Felder zum CFM editor
Der erste Schritt ist das Hinzufügen der Eingabefelder für die beforeSelector und afterSelector Werte im CFM-Editor. Dazu werden wir zwei JSP-Dateien unter diesem Pfad erstellen:
- /apps/dam/cfm/models/editor/components/datatypeproperties/datebeforefield/datebeforefield.jsp
- /apps/dam/cfm/models/editor/components/datatypeproperties/dateafterfield/dateafterfield.jsp
dateafterfield.jsp
<%@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);
HashMap values = new HashMap();
values.put("granite:class", "field-dateafter-descriptor");
values.put("fieldLabel", i18n.get("Date after field selector for validation"));
values.put("name", "./content/items/" + resource.getName() + "/afterSelector");
values.put("value", fieldProperties.get("afterSelector", String.class));
values.put("fieldDescription", "The property name needs to be encapsulated inside this template: [name='PROPERTYNAME']");
values.put("emptyText", "[name='PROPERTYNAME']");
FormResourceManager formResourceManager = sling.getService(FormResourceManager.class);
Resource labelFieldResource = formResourceManager.getDefaultPropertyFieldResource(resource, values);
%>
datebeforefield.jsp
<%@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);
HashMap values = new HashMap();
values.put("granite:class", "field-datebefore-descriptor");
values.put("fieldLabel", i18n.get("Date before field selector for validation"));
values.put("name", "./content/items/" + resource.getName() + "/beforeSelector");
values.put("value", fieldProperties.get("beforeSelector", String.class));
values.put("fieldDescription", "The property name needs to be encapsulated inside this template: [name='PROPERTYNAME']");
values.put("emptyText", "[name='PROPERTYNAME']");
FormResourceManager formResourceManager = sling.getService(FormResourceManager.class);
Resource labelFieldResource = formResourceManager.getDefaultPropertyFieldResource(resource, values);
%>
Beachten Sie, dass afterSelector und beforeSelector einen CSS-Selektor benötigen. Deshalb muss der Property value in einem bestimmten Format vorliegen.
Siehe auch "fieldDescription": [name='PROPERTYNAME']
Nun müssen wir diese Eigenschaftsfelder dem eigentlichen Datepicker für CFMs zuweisen. Wir können dies tun, indem wir eine Datei unter /libs überschreiben/überlagern (overwrite), indem wir diese Datei zum Ordner /apps hinzufügen:
- /apps/settings/dam/cfm/models/formbuilderconfig/datatypes/.content.xml
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="nt:unstructured">
<items jcr:primaryType="nt:unstructured">
<date
jcr:primaryType="nt:unstructured"
fieldProperties="[datepickerfields,labelfield,maptopropertyfield,datetimepickerfield,datevaluefield,requiredfield,datebeforefield,dateafterfield]"/>
</items>
</jcr:root>
Zweiter Schritt: Validierung zum Content Fragment Model hinzufügen
Und das war's im Grunde schon. Jetzt muss der CFM-Autor nur noch den Selektor mit der Eigenschaft zum Inhaltsfragmentmodell hinzufügen, etwa so:
Und dann ist die Validierung für den Autor des Inhaltsfragments aktiv
Ich hoffe, diese kleine Erweiterung hat Ihnen geholfen, und wenn Sie eine ausführlichere Erklärung benötigen, können Sie weiter lesen.
Technische Details
Wenn wir in das Feld Content Fragment Model für Datepicker schauen, finden wir diese Komponente:
- /libs/dam/cfm/models/editor/komponenten/datatentypen/datepicker
Und in den Properties finden wir den resourceSuperType
- /libs/granite/ui/components/coral/foundation/form/datepicker
Dies hilft uns zu sehen, welche Funktionalitäten wir nutzen können und welche "versteckten" Funktionen wir dem CFM-Autor zur Verfügung stellen können.
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 überlagern (overwrite). Denn ein neues AEM-Release kann Änderungen an unseren geänderten Dateien enthalten und zu unvorhergesehenen Problemen führen, da es keine Möglichkeit gibt, herauszufinden, was sich geändert hat, wenn man nicht direkt in die jsp/html/...-Dateien im Ordner /libs schaut.
Aber in diesem Fall ist das Risiko ziemlich gering, da wir neue Dateien hinzufügen, anstatt bestehende zu überlagern. Sie müssen nur die fieldProperties im Auge behalten, da diese in der Zukunft erweitert/geändert werden könnten.
Getestet mit AEM 6.5.17
Wenn Sie wissen möchten, wie Sie das Tag-Feld erweitern können, um "forceSelection" zu aktivieren, klicken Sie bitte hier: