We have a component with icons links and each icon needs to have one of the following two fields completed:
Currently, authors can leave them both blank, which causes a broken link to a non-existent page. How can I write a validation rule that notifies the users that one of the two fields is required?
<internal-link
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/pathfield"
fieldDescription="Select internal link"
fieldLabel="Internal Link"
name="./internalLink"
rootPath="/content/attbusiness/en"/>
<external-link
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldDescription="Link to external page outside"
fieldLabel="External link"
name="./externalLink"/>
Solved! Go to Solution.
Topics help categorize Community content and increase your ability to discover relevant content.
Views
Replies
Total Likes
Hi @Codelime ,
there isn't an out-of-the-box JCR property or mechanism to enforce validation rules like "at least one of two fields must be filled"
But
you can make use of ExtraClientlibs, a sample js here:
(function () {
"use strict";
// Function to validate fields
function validateLinks() {
var internalLink = document.querySelector('coral-pathfield[name="./internalLink"]').value.trim();
var externalLink = document.querySelector('coral-textfield[name="./externalLink"]').value.trim();
if (!internalLink && !externalLink) {
alert("Error: At least one of the fields (Internal Link or External Link) is required.");
return false; // Prevent dialog submission
}
return true; // Allow dialog submission
}
// Add event listener to dialog submit button
document.addEventListener("foundation-contentloaded", function () {
var dialog = document.querySelector(".cq-dialog");
if (dialog) {
var submitButton = dialog.querySelector(".cq-dialog-submit");
if (submitButton) {
submitButton.addEventListener("click", function (event) {
if (!validateLinks()) {
event.preventDefault(); // Prevent dialog submission
}
});
}
}
});
})();
Thank you.
-Sravan
Hi @Codelime ,
there isn't an out-of-the-box JCR property or mechanism to enforce validation rules like "at least one of two fields must be filled"
But
you can make use of ExtraClientlibs, a sample js here:
(function () {
"use strict";
// Function to validate fields
function validateLinks() {
var internalLink = document.querySelector('coral-pathfield[name="./internalLink"]').value.trim();
var externalLink = document.querySelector('coral-textfield[name="./externalLink"]').value.trim();
if (!internalLink && !externalLink) {
alert("Error: At least one of the fields (Internal Link or External Link) is required.");
return false; // Prevent dialog submission
}
return true; // Allow dialog submission
}
// Add event listener to dialog submit button
document.addEventListener("foundation-contentloaded", function () {
var dialog = document.querySelector(".cq-dialog");
if (dialog) {
var submitButton = dialog.querySelector(".cq-dialog-submit");
if (submitButton) {
submitButton.addEventListener("click", function (event) {
if (!validateLinks()) {
event.preventDefault(); // Prevent dialog submission
}
});
}
}
});
})();
Thank you.
-Sravan
Hi @Codelime, there's no need to make two seperate link fields for external and internal. You can use pathfield for external links as well. Just copy paste the external URL in the pathfield and it will work fine.
Using the required = "{Boolean}true" will make the field mandatory. Please find the below code for the same:
<any-link
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/pathfield"
fieldDescription="Select link"
fieldLabel="Link"
name="./Link"
rootPath="/content/attbusiness/en"/
required="{Boolean}true">
If you still insist on adding two fields for external and internal links then you have to write your own custom logic in JS for the same.
Please refer the below link to see the examples for how to apply JS on dialog fields:
https://lucanerlich.com/docs/aem/dialog-validation/
Hi @Codelime ,
HI @Codelime ,
To enforce that one of the two fields (internalLink or externalLink) must be completed in your AEM dialog using Java, you can implement a custom validator. Here's how you can achieve this:
package com.example.core.validation;
import com.adobe.granite.ui.components.Value;
import com.adobe.granite.ui.components.ValueMap;
import com.adobe.granite.ui.validation.AbstractValidator;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.ValueMap;
import java.util.List;
public class RequiredFieldValidator extends AbstractValidator {
@Override
public String getFieldName() {
return "internalLinkOrExternalLink";
}
@Override
public boolean isValid(ValueMap properties) {
String internalLink = properties.get("internalLink", String.class);
String externalLink = properties.get("externalLink", String.class);
return StringUtils.isNotBlank(internalLink) || StringUtils.isNotBlank(externalLink);
}
@Override
public String getErrorMessage() {
return "Please fill in either the Internal Link or External Link field.";
}
}
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="sling:OsgiConfig"
service.pid="com.example.core.validation.RequiredFieldValidator"
sling.servlet.resourceTypes="cq/gui/components/authoring/dialog"
sling.servlet.selectors="validator"
sling.servlet.extensions="json"
sling.servlet.methods="GET"/>
<yourComponent
jcr:primaryType="nt:unstructured"
sling:resourceType="cq/gui/components/authoring/dialog">
<content jcr:primaryType="nt:unstructured">
<items jcr:primaryType="nt:unstructured">
<internal-link
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/pathfield"
fieldDescription="Select internal link"
fieldLabel="Internal Link"
name="./internalLink"
rootPath="/content/attbusiness/en"/>
<external-link
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldDescription="Link to external page outside"
fieldLabel="External link"
name="./externalLink"/>
</items>
</content>
<listeners jcr:primaryType="nt:unstructured"/>
<validators jcr:primaryType="nt:unstructured">
<internalLinkOrExternalLink
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/clientlibs"
fieldDescription="Internal Link or External Link"
allowEmpty="{Boolean}false"/>
</validators>
</yourComponent>
With this implementation, when the dialog is submitted, the validator checks if either the internalLink or externalLink field is filled. If neither field is filled, it returns an error message, and the dialog submission is prevented. Adjust the error handling and messaging as needed to fit your requirements.