Date Range Validation Erweiterung

Freilegen von versteckten Features des CFM Editors von AEM - Teil 1

Zurück zu Insights
/de/de/insights
Teilen

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:

Example of a date field with a before selector
medium
Example of a date field with a after selector
medium
Und dann ist die Validierung für den Autor des Inhaltsfragments aktiv
Author view with failed date validation
medium

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
resourceSuperType for cfm datepicker
medium

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:

Teil 2

Lassen Sie uns Großartiges schaffen!
Wir verwandeln mutige Ideen in echte Ergebnisse. Als Partner für digitale Transformation bringen wir unsere Kunden weiter und gestalten Erlebnisse, die begeistern. Kontaktieren Sie uns und erfahren Sie, wie wir Ihre Visionen zum Leben erwecken.
/content/dam/ews/videos/alex_hands_contact_code_2K_recbitrate.mp4
Let’s talk
/de/de/about-eggs/contact
Ihr nächstes Projekt startet genau hier
Neue Ideen, innovative Herangehensweisen und nachhaltige Lösungen – um diese für Sie zu verwirklichen, müssen wir Ihre Ziele verstehen. Lassen Sie uns gemeinsam den richtigen Weg zum Erfolg gestalten.