diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/FormMetaDataDataSourceServlet.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/FormMetaDataDataSourceServlet.java index 1ecc5b7591..ab49882d58 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/FormMetaDataDataSourceServlet.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/FormMetaDataDataSourceServlet.java @@ -199,15 +199,7 @@ private List getDataSourceResources(SlingHttpServletRequest request, R } } } - // Only add "Custom" option for non-text-input components - String fieldType = ""; - if (config != null) { - String retrievedFieldType = getParameter(config, FIELD_TYPE, request, ""); - fieldType = retrievedFieldType != null ? retrievedFieldType : ""; - } - if (fieldType.isEmpty() || !"text-input".equals(fieldType)) { - resources.add(getResourceForDropdownDisplay(resourceResolver, "Custom", "custom")); - } + resources.add(getResourceForDropdownDisplay(resourceResolver, "Custom", "custom")); break; case SUBMIT_ACTION: // filter the submit actions by uniqueness and data model diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/af-commons/v1/clientlibs/editor/utils/utils.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/af-commons/v1/clientlibs/editor/utils/utils.js index 6cd5b255bc..5100f7e758 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/af-commons/v1/clientlibs/editor/utils/utils.js +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/af-commons/v1/clientlibs/editor/utils/utils.js @@ -177,7 +177,12 @@ let patternComponentParentDiv=patternComponent.closest("div"); patternComponentParentDiv.setAttribute("hidden", true); }else { - // Only handle format component if it exists and is not hidden + // Dropdown exists and is not hidden + // Case 1 : Format component exists and is hidden - Make sure format text field is visible if pattern is not "select" + if(formatComponent && formatComponent.closest("div").hasAttribute("hidden") && displayPatternSelectedValue != "select"){ + formatComponent.closest("div").removeAttribute("hidden"); + } + // Case 2 : Format component exists and is not hidden if (formatComponent && !formatComponent.closest("div").hasAttribute("hidden")) { let displayFormatParentDiv=formatComponent.closest("div"); switch (displayPatternSelectedValue) { @@ -188,12 +193,12 @@ default : displayFormatParentDiv.removeAttribute("hidden"); } + // Only update format component value if it exists and is not hidden + if (displayPatternSelectedValue != "custom") { + formatComponent.value = patternComponent.value; + } } } - // Only update format component value if it exists and is not hidden - if (formatComponent && !formatComponent.closest("div").hasAttribute("hidden") && displayPatternSelectedValue!="custom") { - formatComponent.value = patternComponent.value; - } } } diff --git a/ui.tests/test-module/specs/textinput/textinput.authoring.cy.js b/ui.tests/test-module/specs/textinput/textinput.authoring.cy.js index 84ea30a066..80224389bd 100644 --- a/ui.tests/test-module/specs/textinput/textinput.authoring.cy.js +++ b/ui.tests/test-module/specs/textinput/textinput.authoring.cy.js @@ -172,6 +172,101 @@ describe('Page - Authoring', function () { }); }); }); + + it('verify validation format value is preserved when validation pattern dropdown is not available', function () { + const validationFormatValue = '^[0-9]+$'; + + dropTextInputInContainer(); + cy.openEditableToolbar(sitesSelectors.overlays.overlay.component + textInputEditPathSelector); + cy.invokeEditableAction("[data-action='CONFIGURE']"); + + cy.get('.cmp-adaptiveform-textinput__editdialog').contains('Validation').click({force: true}); + + cy.get('.cmp-adaptiveform-textinput__editdialog').then(($dialog) => { + const $patternDropdown = $dialog.find('.cmp-adaptiveform-textinput__validationpattern'); + // The dropdown can exist in the DOM but not visible when its surrounding container is hidden. + const $patternDropdownWrapper = $patternDropdown[0].closest("div").hasAttribute("hidden"); + const patternDropdownAvailable = $patternDropdown.length > 0 && $patternDropdownWrapper.length === 0; + // If the validation pattern dropdown is not visible, ensure the validation format field preserves the authored value. + if (!patternDropdownAvailable) { + cy.get("[name='./pattern']") + .scrollIntoView() + .should('exist') + .then(($pattern) => { + cy.wrap($pattern).clear({ force: true }).type(validationFormatValue, { force: true }); + }); + cy.get('.cq-dialog-submit').should('be.visible').click(); + cy.reload(); + + cy.openEditableToolbar(sitesSelectors.overlays.overlay.component + textInputEditPathSelector); + cy.invokeEditableAction("[data-action='CONFIGURE']"); + cy.get('.cmp-adaptiveform-textinput__editdialog').contains('Validation').click({force: true}); + cy.get("[name='./pattern']") + .scrollIntoView() + .should('exist') + .should('have.value', validationFormatValue); + cy.get('.cq-dialog-cancel').should('be.visible').click(); + } else { + // Dropdown exists; scroll it into view + cy.wrap($patternDropdown).scrollIntoView().should('be.visible'); + cy.get('.cq-dialog-cancel').should('be.visible').click(); + } + cy.deleteComponentByPath(textInputDrop); + }); + }); + + it('should switch validation pattern dropdown to "Custom" when an unmapped regex is authored', function () { + const customValidationFormatValue = '^custom-regex-[0-9]{3}$'; + + dropTextInputInContainer(); + cy.openEditableToolbar(sitesSelectors.overlays.overlay.component + textInputEditPathSelector); + cy.invokeEditableAction("[data-action='CONFIGURE']"); + + cy.get('.cmp-adaptiveform-textinput__editdialog').contains('Validation').click({force: true}); + cy.get('.cmp-adaptiveform-textinput__validationpattern') + .scrollIntoView() + .should('exist') + .as('validationDropdown'); + cy.get(".cmp-adaptiveform-textinput__validationformat") + .scrollIntoView() + .should('exist') + .as('validationFormat'); + + // Pick a non-default option (not empty, not "custom") so the format field is shown and synced. + let chosenValue; + cy.get('@validationDropdown').find('select[handle="nativeSelect"]').then(($nativeSelect) => { + const options = Array.from($nativeSelect[0]?.options || []); + const chosen = options.find((opt) => + Boolean(opt.value) && + opt.value !== 'custom' && + opt.value !== '#####################.###############' + ); + expect(chosen, 'non-default validation pattern option').to.exist; + chosenValue = chosen.value; + cy.wrap($nativeSelect).select(chosenValue, { force: true }); + cy.wrap($nativeSelect).trigger('change', { force: true }); + }); + cy.then(() => { + cy.get('@validationDropdown').should('have.value', chosenValue); + }); + + // Wait until the wrapper around the format field is un-hidden. + cy.get('@validationFormat').should(($el) => { + const wrapperDiv = $el[0]?.closest('div'); + expect(wrapperDiv?.hasAttribute('hidden')).to.eq(false); + }); + + // Type an unmapped regex into the format field; dropdown should switch to "Custom". + cy.get('@validationFormat') + .clear({ force: true }) + .type(customValidationFormatValue, { force: true }) + .blur({ force: true }); + cy.get('.cq-dialog').click(5, 5, { force: true }); + cy.get('@validationDropdown').should('have.value', 'custom'); + cy.get('@validationDropdown').children('button').should('contain.text', 'Custom'); + cy.get('.cq-dialog-cancel').should('be.visible').click(); + cy.deleteComponentByPath(textInputDrop); + }); }) context('Open Sites Editor', function () {