Steps to create a custom appearance
The steps, at a high level, to create a custom appearance are as follows:
-
Create a project: Create a Maven project that generates a content package to deploy on AEM.
-
Extend an existing widget class: Extend an existing widget class and override the required classes.
-
Create a client library: Create a
clientLib: af.customwidget
library and add the required JavaScript and CSS files. -
Build and install the project: Build the Maven project and install the generated content package on AEM.
-
Update the adaptive form: Update adaptive form field properties to use the custom appearance.
Create a project
A maven archetype is a starting point for creating a custom appearance. The details of the archetype to be used are as follows:
- Repository: https://repo1.maven.org/maven2/com/adobe/
- Artifact Id: custom-appearance-archetype
- Group Id: com.adobe.aemforms
- Version: 1.0.4
Execute the following command to create a local project based on the archetype:
mvn archetype:generate -DarchetypeRepository=https://repo1.maven.org/maven2/com/adobe/ -DarchetypeGroupId=com.adobe.aemforms -DarchetypeArtifactId=custom-appearance-archetype -DarchetypeVersion=1.0.4
The command downloads the Maven plugins and archetype information from the repository, and generates a project based on the following information:
- groupId: Group ID used by the generated Maven project
- artifactId: Artifact ID used by the generated Maven project.
- version: Version for the generated Maven project.
- package: Package used for the file structure.
- artifactName: Artifact name of the generated AEM package.
- packageGroup: Package group of the generated AEM package.
- widgetName: Appearance name used for reference.
The generated project has the following structure:
─<artifactId>
└───src
└───main
└───content
└───jcr_root
└───etc
└───clientlibs
└───custom
└───<widgetName>
├───common [client library - af.customwidgets which encapsulates below clientLibs]
├───integration [client library - af.customwidgets.<widgetName>_widget which contains template files for integrating a third-party plugin with Adaptive Forms]
│ ├───css
│ └───javascript
└───jqueryplugin [client library - af.customwidgets.<widgetName>_plugin which holds the third-party plugins and related dependencies]
├───css
└───javascript
Extend an existing widget class
Once the project template is created, do the following changes, as required:
-
Include the third-party plugin dependency to the project.
-
Place the third-party or custom jQuery plugins in the
jqueryplugin/javascript
folder and related CSS files in thejqueryplugin/css
folder. For more details, see the JS and CSS files under thejqueryplugin/javascript and jqueryplugin/css
folder. -
Modify the
js.txt
andcss.txt
files to include any additional JavaScript and CSS file of the jQuery plugin.
-
-
Integrate the third-party plugin with the framework to enable interaction between the custom appearance framework and the jQuery plugin. The new widget will be functional only after you extend or override the following functions.
-
Update the JavaScript file in the
integration/javascript
folder, as required.-
Replace the text
__widgetName__
with the actual widget name. -
Extend the widget from a suitable out-of-the-box widget class. In most cases, It is the widget class corresponding to the existing widget being replaced. The parent class name is used at multiple locations, so it is recommended to search for all instances of the string
xfaWidget.textField
in the file, and replace them with the actual parent class used. -
Extend the
render
method to provide an alternate UI. It is the location from where the jQuery plugin will be invoked to update the UI or the interaction behavior. Therender
method should return a user-control element. -
Extend the
getOptionsMap
method to override any option setting impacted due to a change in the widget. The function returns a mapping that provides details for the action to perform on change of an option. The keys are the options provided to the widget and the values are the functions called whenever a change in the option is detected. -
The
getEventMap
method maps events triggered by the widget, with the events required by the adaptive form model. The default value maps standard HTML events for the default widget, and needs to be updated if an alternate event is triggered. -
The
showDisplayValue
andshowValue
apply the display and edit picture clause and can be overridden to have an alternate behavior. -
The
getCommitValue
method is called by the adaptive forms framework when thecommit
event occurs. Generally, it is the exit event, except for the dropdown, radio button, and check box elements where it occurs on change). For more information, see Adaptive Forms Expressions. -
The template file provides sample implementation for various methods. Remove methods that are not to be extended.
-
Create a client library
The sample project generated by the Maven archetype automatically creates required client libraries, and wraps them into a client library with a category af.customwidgets
. The JavaScript and CSS files available in the af.customwidgets
are automatically included at runtime.
Build and install
To build the project, execute the following command on the shell to generate a CRX package that needs to be installed on the AEM server.
mvn clean install
settings.xml
file.Update the adaptive form
To apply the custom appearance to an adaptive form field:
- Open the adaptive form in edit mode.
- Open the Property dialog for the field on which you want to apply the custom appearance.
- In the Styling tab, update the
CSS class
property to add the appearance name in thewidget_<widgetName>
format. For example: widget_numericstepper
Sample: Create a custom appearance
Let’s now look at an example to create a custom appearance for a numeric field to appear as a numeric stepper or slider. Perform the following steps:
-
Execute the following command to create a local project based on Maven archetype:
mvn archetype:generate -DarchetypeRepository=https://repo1.maven.org/maven2/com/adobe/ -DarchetypeGroupId=com.adobe.aemforms -DarchetypeArtifactId=custom-appearance-archetype -DarchetypeVersion=1.0.4
It prompts you to specify values for the following parameters.
The values used in this sample are highlighted in bold.Define value for property 'groupId': com.adobe.afwidgets
Define value for property 'artifactId': customWidgets
Define value for property 'version': 1.0.1-SNAPSHOT
Define value for property 'package': com.adobe.afwidgets
Define value for property 'artifactName': customWidgets
Define value for property 'packageGroup': adobe/customWidgets
Define value for property 'widgetName': numericStepper
-
Navigate to the
customWidgets
(specified value for theartifactID
property) directory and execute the following command to generate an Eclipse project:mvn eclipse:eclipse
-
Open the Eclipse tool and do the following to import the Eclipse project:
-
Select File > Import > Existing Projects into Workspace.
-
Browse and select the folder where you executed the
archetype:generate
command. -
Click Finish.
-
-
Select the widget to be used for the custom appearance. This sample uses the following numeric stepper widget:
https://www.jqueryscript.net/form/User-Friendly-Number-Input-Spinner-with-jQuery-Bootstrap.html
In the Eclipse project, review the plug-in code in the
plugin.js
file to ensure that it matches the requirements for the appearance. In this sample, the appearance fulfills the following requirements:-
The numeric stepper should extend from
- $.xfaWidget.numericInput
. -
The
set value
method of the widget sets the value after the focus is on the field. It is a mandatory requirement for an adaptive form widget. -
The
render
method needs to be overridden to invoke thebootstrapNumber
method. -
There is no additional dependency for the plugin other than the main source code of the plugin.
-
The sample does not perform any styling on the stepper, so no additional CSS is required.
-
The
$userControl
object should be available to therender
method. It is a field of thetext
type which is cloned with the plugin code. -
The + and - buttons should be disabled when the field is disabled.
-
-
Replace the contents of the
bootstrap-number-input.js
(jQuery plugin) with the content of thenumericStepper-plugin.js
file. -
In the
numericStepper-widget.js
file, add the following code to override the render method to invoke the plugin and return the$userControl
object:render : function() { var control = $.xfaWidget.numericInput.prototype.render.apply(this, arguments); var $control = $(control); var controlObject; try{ if($control){ $control.bootstrapNumber(); var id = $control.attr("id"); controlObject = $("#"+id); } }catch (exc){ console.log(exc); } return controlObject; }
-
In the
numericStepper-widget.js
file, override thegetOptionsMap
property to override the access option, and hide the + and - buttons in disabled mode.getOptionsMap: function(){ var parentOptionsMap = $.xfaWidget.numericInput.prototype.getOptionsMap.apply(this,arguments), newMap = $.extend({},parentOptionsMap, { "access": function(val) { switch(val) { case "open" : this.$userControl.removeAttr("readOnly"); this.$userControl.removeAttr("aria-readonly"); this.$userControl.removeAttr("disabled"); this.$userControl.removeAttr("aria-disabled"); this.$userControl.parent().find(".input-group-btn button").prop('disabled',false); break; case "nonInteractive" : case "protected" : this.$userControl.attr("disabled", "disabled"); this.$userControl.attr("aria-disabled", "true"); this.$userControl.parent().find(".input-group-btn button").prop('disabled',true); break; case "readOnly" : this.$userControl.attr("readOnly", "readOnly"); this.$userControl.attr("aria-readonly", "true"); this.$userControl.parent().find(".input-group-btn button").prop('disabled',true); break; default : this.$userControl.removeAttr("disabled"); this.$userControl.removeAttr("aria-disabled"); this.$userControl.parent().find(".input-group-btn button").prop('disabled',false); break; } }, }); return newMap; }
-
Save the changes, navigate to the folder containing the
pom.xml
file, and execute the following Maven command to build the project:mvn clean install
-
Install the package using AEM Package Manager.
-
Open the adaptive form in edit mode on which you want to apply the custom appearance and do the following:
-
Right-click the field on which you want to apply the appearance and click Edit to open the Edit Component dialog.
-
In the Styling tab, update the CSS class property to add
widget_numericStepper
.
-
The new appearance you created is now available for use.
Experience Manager
Espressos & Experience Manager: AEM Forms
Espressos & Experience Manager
Thursday, Mar 6, 7:00 PM UTC
Join Adobe's AEM product team as they highlight AEM Forms' latest innovations, including: the new Gen AI Assistant, Unified Composition with AEM Sites, and new ways to deploy forms through conversations.
RegisterAdobe Experience Manager Forms at Summit
Register for these sessions:
- Elevate and Empower Teams with Agentic AI for Exceptional Experiences (attend online)
- The Future of Forms: Experience Success Across the Enrollment Journey (attend online)
- The True Cost of a Failed Implementation (attend online)
- Put the Customer at the Center and Build Relationships That Last a Lifetime (attend online)
- Driving Marketing Agility and Scale: Transforming your Content Supply Chain with AI (attend online)
Connect with Experience League at Summit!
Get front-row access to top sessions, hands-on activities, and networking—wherever you are!
Learn more