AEM CQ 56 - Adding a custom property in create page dialog

Goal


Add a new field in create page dialog for storing additional page information. Here we add Description field in create page dialog. Source codePackage Install and Demo Video are available for download




Prerequisites


If you are new to CQ

1) Read this post on how to create a sample page component

2) Read this post on how to setup your IDE and create an OSGI component

UI Changes - Solution 1


1) Login to CRXDE Lite, create folder (nt:folder) /apps/createpagecustomprop

2) Create clientlib (type cq:ClientLibraryFolder) /apps/createpagecustomprop/clientlib and set a property categories of String type to cq.widgets

3) Create file ( type nt:file ) /apps/createpagecustomprop/clientlib/js.txt, add the following

                         customprop.js

4) Create file ( type nt:file ) /apps/createpagecustomprop/clientlib/customprop.js, add the following code

(function(){
    //the original create page dialog fn
    var cqCreatePageDialog = CQ.wcm.Page.getCreatePageDialog;

    //override ootb function and add description field
    CQ.wcm.Page.getCreatePageDialog = function(parentPath){
        //create dialog by executing the product function
        var dialog = cqCreatePageDialog(parentPath);

        //make necessary UI changes to the dialog created above
        var panel = dialog.findBy(function(comp){
            return comp["jcr:primaryType"] == "cq:Panel";
        }, dialog);

        if(panel && panel.length > 0){
            var description = new CQ.Ext.form.TextArea({
                "fieldLabel": "Description",
                "name": "pageDescription"
            });

            panel[0].insert(2,description);
            panel[0].doLayout();

            dialog.params.cmd = "createPageWithDescription";

            var cmdField = dialog.formPanel.findBy(function(comp){
                return comp["name"] == "cmd";
            }, dialog.formPanel);

            cmdField[0].setValue("createPageWithDescription");
        }
        return dialog;
    }
})();

UI Changes - Solution 2


Not a preferred way of doing UI override as it doesn't minify /libs/cq/ui/widgets/source/widgets/wcm/Page.Actions.js

1) We use the overlay architecture of CQ to modify (extend) create page dialog, CQ.wcm.Page.getCreatePageDialog

2) The logic for page create dialog is available in js file /libs/cq/ui/widgets/source/widgets/wcm/Page.Actions.js. So, to overlay the actions available in this file, create path /apps/cq/ui/widgets/source/widgets/wcm

3) Create file Page.Actions.js under /apps/cq/ui/widgets/source/widgets/wcm and add the following code. Here we are loading the ootb page actions file and in a way extending CQ.wcm.Page.getCreatePageDialog to add a textarea field - Description

//load ootb page actions
$.getScript("/libs/cq/ui/widgets/source/widgets/wcm/Page.Actions.js", function(){

    //the original create page dialog fn
    var cqCreatePageDialog = CQ.wcm.Page.getCreatePageDialog;

    //override ootb function and add description field
    CQ.wcm.Page.getCreatePageDialog = function(parentPath){
        //create dialog by executing the product function
        var dialog = cqCreatePageDialog(parentPath);

        //make necessary UI changes to the dialog created above
        var panel = dialog.findBy(function(comp){
            return comp["jcr:primaryType"] == "cq:Panel";
        }, dialog);

        if(panel && panel.length > 0){
            var description = new CQ.Ext.form.TextArea({
                "fieldLabel": "Description",
                "name": "pageDescription"
            });

            panel[0].insert(2,description);
            panel[0].doLayout();

            dialog.params.cmd = "createPageWithDescription";

            var cmdField = dialog.formPanel.findBy(function(comp){
                return comp["name"] == "cmd";
            }, dialog.formPanel);

            cmdField[0].setValue("createPageWithDescription");
        }
        return dialog;
    }
});

4) In #32 above, we are overriding ootb create page command with a custom page command createPageWithDescription. The necessary logic for creating a custom command is explained in next section.

5) When a user enters page title, description etc and clicks ok, the request is POSTed to /bin/wcmcommand (check /libs/cq/ui/widgets/source/widgets/wcm/Page.Actions.js, CQ.wcm.Page.getCreatePageDialog function). Ootb, the cmd param to this servlet is createPage,  replaced with createPageWithDescription.

Create Command Bundle


1) Create a bundle with java class CustomPropertyPageCreateCommand and add the following code. Implementing WCMCommand and returning the custom action name in getCommandName() method executes this command by /bin/wcmcommand servlet if a request is sent with respective cmd param. Here its createPageWithDescription. The rest of class is pretty straightforward, create page using page manager api and set jcr:description with value entered in the description UI field

package apps.mysample.pagecustomprop;

import com.day.cq.commons.servlets.HtmlStatusResponseHelper;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import com.day.cq.wcm.api.commands.WCMCommand;
import com.day.cq.wcm.api.commands.WCMCommandContext;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.HtmlResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.Node;
import javax.jcr.Session;

@Component
@Service
public class CustomPropertyPageCreateCommand implements WCMCommand {

    private static final Logger log = LoggerFactory.getLogger(CustomPropertyPageCreateCommand.class);

    public String getCommandName() {
        return "createPageWithDescription";
    }

    public HtmlResponse performCommand(WCMCommandContext commandContext,
                                       SlingHttpServletRequest request, SlingHttpServletResponse response,
                                       PageManager pageManager) {
        HtmlResponse resp = null;

        try {
            String parentPath = request.getParameter(PARENT_PATH_PARAM);
            String pageLabel = request.getParameter(PAGE_LABEL_PARAM);
            String template = request.getParameter(TEMPLATE_PARAM);
            String pageTitle = request.getParameter(PAGE_TITLE_PARAM);
            String pageDescription = request.getParameter("pageDescription");

            Page page = pageManager.create(parentPath, pageLabel, template,pageTitle);

            Session session = request.getResourceResolver().adaptTo(Session.class);
            Node pageNode = page.adaptTo(Node.class);

            Node contentNode = pageNode.getNode("./" + Node.JCR_CONTENT);
            contentNode.setProperty("jcr:description", pageDescription);

            session.save();

            resp = HtmlStatusResponseHelper.createStatusResponse(true, "Page created", page.getPath());
        } catch (Exception e) {
            log.error("Error during page creation.", e);
            resp = HtmlStatusResponseHelper.createStatusResponse(false, e.getMessage());
        }

        return resp;
    }
}




3 comments: