Tuesday, June 4, 2013

How to create a custom xtype element for Dialogs ? How to make it as a replicant ?

We can create a custom xtype using the out of the box xtypes from AEM. We can do it using the compositeField. Composite field allows a number of form Fields to be rendered on the same row. We use EXT JS to extend Composite Field and add all the required fields into it as a list. Then, we can register this Class as a custom xtype.

Any user who needs this list of fields together can directly use this custom xtype while developing dialogs instead of creating them individually.  We can use this custom xtype as a mutilfield to make it as a replicant.
Code and Steps are given below.

1) Registering the Custom Component :  Create a Javascript file in Client Lib folder and add that into the Component JSP. This Javascript file is used to create the custom xtype and then register it to with EXT JS , so that it can be used in Dialogs.

CustomPathField.js
----------------------------------------------------------------------------------------------------------------------------------
/**
* @class MyClientLib.CustomPathFieldWidget
* @extends CQ.form.CompositeField
* This is a custom path field with a Link Text and a Link URL
* @param {Object} config the config object
*/
/**
* @class Ejst.CustomWidget
* @extends CQ.form.CompositeField
* This is a custom widget based on {@link CQ.form.CompositeField}.
* @constructor
* Creates a new CustomWidget.
* @param {Object} config The config object
*/

CQ.form.CustomMultiField = CQ.Ext.extend(CQ.form.CompositeField, {
/**
* @private
* @type CQ.Ext.form.TextField
*/
hiddenField: null,
/**
* @private
* @type CQ.Ext.form.TextField
*/
linkText: null,
/**
* @private
* @type CQ.Ext.form.PathField
*/
linkURL: null,
/**
* @private
* @type CQ.Ext.form.CheckBox
*/
openInNewWindow: null,

constructor: function (config) {
config = config || {};
var defaults = {
    "border": true,
    "labelWidth": 75,
    "layout": "form"
};
config = CQ.Util.applyDefaults(config, defaults);
CQ.form.CustomMultiField.superclass.constructor.call(this, config);
},
initComponent: function () {

    CQ.form.CustomMultiField.superclass.initComponent.call(this);
    // Hidden field
    this.hiddenField = new CQ.Ext.form.Hidden({
         name: this.name
    });
    this.add(this.hiddenField);

// Text TextField to enter Title
    this.linkText = new CQ.Ext.form.TextField({
        cls: "customwidget-1",
        maxLength: 100,
        emptyText: "Enter Title",
        maxLengthText: "A maximum of 100 characters is allowed for the Link Text.",
        width: 335,
        allowBlank: true,
        name : "item",
        listeners: {
        change: {
        scope: this,
        fn: this.updateHidden
    }
    }
    });
    this.add(this.linkText);

// Link PathField to map a URL
  this.linkURL = new CQ.form.PathField({
        cls: "customwidget-2",
        allowBlank: true,
        emptyText: "Enter Title URL",
width: 335,
        listeners: {
         change: {
            scope: this,
            fn: this.updateHidden
        },    
        dialogclose: {
            scope: this,
            fn: this.updateHidden
        }
       }
    });
    this.add(this.linkURL);

    // Link openInNewWindow
    this.openInNewWindow = new CQ.Ext.form.Checkbox({
        cls: "customwidget-3",
        boxLabel: "New window",
        listeners: {
        change: {
        scope: this,
        fn: this.updateHidden
        },
        check: {
        scope: this,
        fn: this.updateHidden
    }
    }
    });
    this.add(this.openInNewWindow);
},
processInit: function (path, record) {
    this.linkText.processInit(path, record);
    this.linkURL.processInit(path, record);
    this.openInNewWindow.processInit(path, record);
},
setValue: function (value) {
    var link = JSON.parse(value);
    this.linkText.setValue(link.text);
    this.linkURL.setValue(link.url);
    this.openInNewWindow.setValue(link.openInNewWindow);
},
getValue: function () {
    return this.getRawValue();
},
getRawValue: function () {
    var link = {
    "url": this.linkURL.getValue(),
    "text": this.linkText.getValue(),
    "openInNewWindow": this.openInNewWindow.getValue()
    };
    return JSON.stringify(link);
},
updateHidden: function () {
this.hiddenField.setValue(this.getValue());
}
});
CQ.Ext.reg("CustomMultiField", CQ.form.CustomMultiField);
----------------------------------------------------------------------------------------------------------------------------------
When this Javascript is executed you should have the CustomMultiField as xtype.

2) Using the Custom Component in Dialog: Use this xtype in the Dialog to see all the 3 fields ( Text Field, Link Field , Open in New Window )  displayed as a set.  For example, if we want to display them as a multifield, here is how the dialog.xml should look like.

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
    jcr:primaryType="cq:Dialog"
    width="550"
    xtype="dialog">
    <items
        jcr:primaryType="cq:Widget"
        xtype="tabpanel">
        <items jcr:primaryType="cq:WidgetCollection">
            <tab1
                jcr:primaryType="cq:Panel"
                title="Links Component">
                <items jcr:primaryType="cq:WidgetCollection">
                    <links
                        jcr:primaryType="cq:Widget"
                        border="false"
                        fieldDescription="Press + to add more links"
                        fieldLabel="Links"
                        hideLabel="true"
                        name="./links"
                        xtype="multifield">
                        <fieldConfig
                            jcr:primaryType="cq:Widget"
                            xtype="CustomMultiField"/>
                    </links>

                </items>
            </tab1>
        </items>
    </items>
</jcr:root>


3 comments:

  1. Thanks for posting this. Can you please attach some screen shots with each of the steps and also how the final Dialog looks? As they say a picture is worth a 1000 words I am sure it will help novice developers (like me) to make the most out of it.
    thanks

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete