Goal
Create a simple 3 step wizard, say for selecting assets in a path, provide additional information in steps and submit for processing; useful for creating custom screens the "AEM way"
Demo | Package Install
The Wizard - http://localhost:4502/apps/eaem-sample-wizard/eaem-3-step-wizard.html
Wizard Structure in CRX
Solution
1) Login to CRXDE Lite - http://localhost:4502/crx/de/index.jsp and create nt:folder /apps/eaem-sample-wizard
2) Create /apps/eaem-sample-wizard/eaem-3-step-wizard of type cq:Page with the following content
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="cq:Page">
<jcr:content
jcr:mixinTypes="[sling:VanityPath]"
jcr:primaryType="nt:unstructured"
jcr:title="EAEM 3 Step Wizard"
sling:resourceType="/apps/eaem-sample-wizard/page">
<head jcr:primaryType="nt:unstructured">
<viewport
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/admin/page/viewport"/>
<favicon
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/page/favicon"/>
<clientlibs
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/includeclientlibs"
categories="[coralui3,granite.ui.coral.foundation,eaem.wizard]"/>
</head>
<body
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/page/body">
<items jcr:primaryType="nt:unstructured">
<form
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form"
action="/apps/eaem-sample-wizard/eaem-3-step-wizard/jcr:content"
foundationForm="{Boolean}true"
maximized="{Boolean}true"
method="post"
novalidate="{Boolean}true"
style="vertical">
<successresponse
jcr:primaryType="nt:unstructured"
jcr:title="Success"
sling:resourceType="granite/ui/components/coral/foundation/form/responses/openprompt"
open="/apps/eaem-sample-wizard/eaem-3-step-wizard.html"
redirect="/apps/eaem-sample-wizard/eaem-3-step-wizard.html"
text="Your data was submitted"/>
<items jcr:primaryType="nt:unstructured">
<charset
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/hidden"
name="_charset_"
value="utf-8"/>
<wizard
jcr:primaryType="nt:unstructured"
jcr:title="Experience AEM 3 Step Wizard"
sling:resourceType="granite/ui/components/coral/foundation/wizard">
<items jcr:primaryType="nt:unstructured">
<step1
jcr:primaryType="nt:unstructured"
jcr:title="Step One"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<title
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/section">
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"
margin="{Boolean}false"/>
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/container">
<items jcr:primaryType="nt:unstructured">
<assetsPath
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/pathbrowser"
fieldLabel="Assets Path"
name="eaemAssetsPath"
rootPath="/content/dam"/>
</items>
</column>
</items>
</title>
</items>
<parentConfig jcr:primaryType="nt:unstructured">
<next
granite:class="foundation-wizard-control"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/button"
text="Next"
variant="primary">
<granite:data
jcr:primaryType="nt:unstructured"
foundation-wizard-control-action="next"/>
</next>
</parentConfig>
</step1>
<step2
jcr:primaryType="nt:unstructured"
jcr:title="Step Two"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<list
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/include"
path="/libs/dam/gui/content/assets/jcr:content/views/list"/>
</items>
<parentConfig jcr:primaryType="nt:unstructured">
<next
granite:class="foundation-wizard-control"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/button"
text="Next"
variant="primary">
<granite:data
jcr:primaryType="nt:unstructured"
foundation-wizard-control-action="next"/>
</next>
</parentConfig>
</step2>
<step3
jcr:primaryType="nt:unstructured"
jcr:title="Step Three"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<footer
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/section">
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"
margin="{Boolean}false"/>
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/container">
<items jcr:primaryType="nt:unstructured">
<text
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textarea"
fieldLabel="Text"
name="eaemText"/>
</items>
</column>
</items>
</footer>
</items>
<parentConfig jcr:primaryType="nt:unstructured">
<next
granite:class="foundation-wizard-control"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/button"
text="GO"
type="submit"
variant="primary">
<granite:data
jcr:primaryType="nt:unstructured"
foundation-wizard-control-action="next"/>
</next>
</parentConfig>
</step3>
</items>
<granite:data
jcr:primaryType="nt:unstructured"
suffix="${requestPathInfo.suffix}"/>
</wizard>
</items>
</form>
</items>
</body>
</jcr:content>
</jcr:root>
3) The extension clientlib #19, for page created above, eaem.wizard is added in next steps
4) #69, in step 1, select the folder path from where assets are to be picked
5) #98, in step 2, provide a list view of the assets in folder, selected in step 1; list view here includes otb list view from Assets Console http://localhost:4502/assets.html/content/dam - /libs/dam/gui/content/assets/jcr:content/views/list
6) #133, in step 3, provide a text area widget for entering additional information
7) #28 has the wizard form action /apps/eaem-sample-wizard/eaem-3-step-wizard/jcr:content of sling:resourceType /apps/eaem-sample-wizard/page
8) Create /apps/eaem-sample-wizard/page with the following content
<?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:Folder"
sling:resourceSuperType="granite/ui/components/coral/foundation/page"/>
9) Create nt:file /apps/eaem-sample-wizard/page/POST.jsp with the necessary logic to process selected assets, entered content submitted in step 3 of the wizard
<%@include file="/libs/granite/ui/global.jsp"%>
<%@page session="false"%>
<%
String eaemSelectedAssets = request.getParameter("eaemSelectedAssets");
String eaemText = request.getParameter("eaemText");
//PROCESS THE SELECTED ASSETS
log.info("eaemText-------" + eaemText);
log.info("eaemSelectedAssets-------" + eaemSelectedAssets);
%>
10) Create clientlib (type cq:ClientLibraryFolder) /apps/eaem-sample-wizard/clientlib with categories=eaem.wizard and dependencies=underscore to add some dynamic behavior to the wizard while navigating between the steps
11) Create nt:file /apps/eaem-sample-wizard/clientlib/js.txt and add the following content
handle-wizard.js
12) Create nt:file /apps/eaem-sample-wizard/clientlib/handle-wizard.js, add the following logic
(function ($, $document) {
var WIZARD_URL = "/apps/eaem-sample-wizard/eaem-3-step-wizard.html",
SUFFIX = "suffix",
EAEM_ASSETS_PATH = "eaemAssetsPath",
EAEM_SELECTED_ASSETS = "eaemSelectedAssets";
$document.on("foundation-contentloaded", moveToStep2IfSuffixAvailable);
$document.on("foundation-wizard-stepchange", handleSteps);
function moveToStep2IfSuffixAvailable(){
var $wizard = $(".foundation-wizard");
if(_.isEmpty($wizard)){
return;
}
var suffix = $wizard.data(SUFFIX);
if(_.isEmpty(suffix)){
return;
}
var wizardApi = $wizard.adaptTo("foundation-wizard");
wizardApi.next();
}
function getStepNumber(){
var $wizard = $(".foundation-wizard"),
currentStep = $wizard.find(".foundation-wizard-step-active"),
wizardApi = $wizard.adaptTo("foundation-wizard");
return wizardApi.getPrevSteps(currentStep).length + 1;
}
function isSecondStep(){
return (getStepNumber() === 2);
}
function isThirdStep(){
return (getStepNumber() === 3);
}
function handleSteps(event, nextStep, currentStep){
if(_.isUndefined(currentStep)){
return;
}
var $eaemAssetsPath = $("[name=" + EAEM_ASSETS_PATH + "]");
if(isSecondStep() && !_.isEmpty($eaemAssetsPath.val())){
$(nextStep).hide();
redirectTo(WIZARD_URL + $eaemAssetsPath.val());
}else if(isThirdStep()){
addSelectedAssetsToForm();
}
}
function addSelectedAssetsToForm(){
var $form = $("form"), assetPaths = [],
eaemSelectedAssets = $("[name=" + EAEM_SELECTED_ASSETS + "]");
if(_.isEmpty(eaemSelectedAssets)){
eaemSelectedAssets = $('<input />').attr('type', 'hidden')
.attr('name', EAEM_SELECTED_ASSETS)
.appendTo($form);
}
$(".foundation-selections-item").each(function(index, asset){
assetPaths.push($(asset).data("foundation-collection-item-id"));
});
eaemSelectedAssets.val(assetPaths.join(","));
}
function redirectTo(url){
var ui = $(window).adaptTo("foundation-ui");
ui.wait($("form"));
window.location = url;
}
}(jQuery, jQuery(document)));