Using and Extending Widgets

You are reading the Adobe Experience Manager 5.6.1 version of Using and Extending Widgets.
This documentation is also available for the following versions: AEM 5.6  CQ 5.5  CQ 5.4  CQ 5.3 

Adobe Experience Manager's web-based interface uses AJAX and other modern browser technologies to enable WYSIWYG editing and formatting of content by authors right on the web page.

Adobe Experience Manager (AEM) uses the ExtJS widgets library, which provides the highly polished user interface elements that work across all the most important browsers and allow the creation of desktop-grade UI experiences.

These widgets are included within AEM and, in addition to being used by AEM itself, can be used by any website built using AEM.

For a complete reference of all the available widgets in AEM you can refer to the widget API documentation or to the list of existing xtypes. In addition, many examples showing how to use the ExtJS framework are available on the Sencha site, the owner of the framework.

This page gives some insights about how to use and extend widgets. It first describes how to include client-sided code in a page. It then describes some sample components that have been created to illustrate some basic use and extension. Those components are available in the Using ExtJS Widgets package on Package Share.

The package includes examples of:

Note

Adobe Experience Manager is built upon ExtJS 3.4.0.

Including the Client-Sided Code in a Page

Client sided javascript and stylesheet code should be placed in a client library.

To create a client library:

  1. Create a node below /apps/<project> with the following properties:
    • jcr:primaryType="cq:ClientLibraryFolder"
    • name="clientlib"
    • jcr:mixinTypes="[mix:lockable]"
    • sling:resourceType="widgets/clientlib"
    • categories="[<category-name>]"
    • dependencies="[cq.widgets]"
    Note: <category-name> is the name of the custom library (e.g. "cq.extjstraining") and is used to include the library on the page.
  2. Below clientlib create the css and js folders (nt:folder).
  3. Below clientlib create the css.txt and js.txt files (nt:files). Those .txt files list the files that are included in the library.
  4. Edit js.txt: it needs to start with '#base=js' followed by the list of the files that will be aggregated by the CQ client library service, eg:
    #base=js
    components.js
    exercises.js
    CustomWidget.js
    CustomBrowseField.js
    InsertTextPlugin.js
  5. Edit css.txt: it needs to start with '#base=css' followed by the list of the files that will be aggregated by the CQ client library service, eg:
    #base=css
    components.css
  6. Below the js folder, place the javascript files that belong to the library.
  7. Below the css folder, place the .css files and the resources used by the css files (e.g. my_icon.png).

Note

The handling of stylesheets described before is optional.

To include the client library in the page component jsp:

  • to include both javascript code and stylesheets:
    <cq:includeClientLib categories="<category-name1>, <category-name2>, ..."/>
    where <category-nameX> is the name of the client-sided library.
  • to only include javascript code:
    <cq:includeClientLib js="<category-name>"/>

For more details refer to the description of the <cq:includeClientLib> tag.

In some cases a client library should only be available in author mode and should be excluded in publish mode. It can be achieved as follows:

    if (WCMMode.fromRequest(request) != WCMMode.DISABLED) {
        %><cq:includeClientLib categories="cq.collab.blog"/><%
    }
        

Getting Started with the Samples

To follow the tutorials on this page, install the package called Using ExtJS Widgets in a local AEM instance and create a sample page in which the components will be included. To do so:

  1. In your AEM instance download the package called Using ExtJS Widgets (v01) from Package Share and install the package. It creates the project extjstraining below /apps in the repository.
  2. Include the client library containing the scripts (js)  and the stylesheet (css) in the head tag of the geometrixx page jsp, as you will include the sample components in a new page of the Geometrixx branch:
    in CRXDE Lite open the file /apps/geometrixx/components/page/headlibs.jsp and add the cq.extjstraining category to the existing <cq:includeClientLib> tag as follows:
    %><cq:includeClientLib categories="apps.geometrixx-main, cq.extjstraining"/><%
  3. Create a new page in the Geometrixx branch below /content/geometrixx/en/products and call it Using ExtJS Widgets.
  4. Go in design mode and add all the components of the group called Using ExtJS Widgets to the design of Geometrixx
  5. Go back in edit mode: the components of the group Using ExtJS Widgets are available in the Sidekick.

Note

For more info on installing the Using ExtJS Widgets package, see How to Work With Packages.

Basic Dialogs

Dialogs are typically used to edit content, but can also just display information. An easy way to view a complete dialog is to access its representation in json format. To do so, point your browser to:

http://localhost:4502/<path-to-dialog>.-1.json

The first component of the Using ExtJS Widgets group in the Sidekick is called 1. Dialog Basics and includes four basic dialogs that are built with out-of-the-box widgets and without customized javascript logic. The dialogs are stored below /apps/extjstraining/components/dialogbasics. The basic dialogs are:

  • the Full dialog (full node): it displays a window with 3 tabs, each tab having 2 text fields.
  • the Single Panel dialog(singlepanel node): it displays a window with 1 tab that has 2 text fields.
  • the Multi Panel dialog(multipanel node): its display is the same as the Full dialog but it is built differently.
  • the Rich dialog(rich node): it displays a window with 2 tabs. The first tab has a text field, a drop-down menu and a collapsible textarea. The second tab has a field set with 4 text fields and a collapsible field set with 2 text fields.

Include the 1. Dialog Basics component in the sample page:

  1. Add the 1. Dialog Basics component to the sample page from the Using ExtJS Widgets tab in the Sidekick.
  2. The component displays a title, some text and a PROPERTIES link: click the link to display the properties of the paragraph stored in the repository. Click again the link to hide the properties.

The component displays as follows:

file

Example 1: Full Dialog

The Full dialog displays a window with three tabs, each tab having two text fields. It is the default dialog of the Dialog Basics component. Its characteristics are:

  • Is defined by a node: node type = cq:Dialog, xtype = dialog.
  • Displays 3 tabs (node type = cq:Panel).
  • Each tab has 2 textfields (node type = cq:Widget, xtype = textfield).
  • Is defined by the node:
    /apps/extjstraining/components/dialogbasics/full
  • Is rendered in json format by requesting:
    http://localhost:4502/apps/extjstraining/components/dialogbasics/full.-1.json

The dialog displays as follows:

file

Example 2: Single Panel Dialog

The Single Panel dialog displays a window with one tab that has two text fields. Its characteristics are:

 

  • Displays 1 tab (node type = cq:Dialog, xtype = panel)
  • The tab has 2 textfields (node type = cq:Widget, xtype = textfield)
  • Is defined by the node:
    /apps/extjstraining/components/dialogbasics/singlepanel
  • Is rendered in json format by requesting:
    http://localhost:4502/apps/extjstraining/components/dialogbasics/singlepanel.-1.json
  • One advantage over the Full Dialog is that less configuration is needed.
  • Recommended use: for simple dialogs that display information or only have just a few fields.

To use the Single Panel dialog:

  1. Replace the dialog of the Dialog Basics component with the Single Panel dialog:

    1. In CRXDE Lite, delete the node: /apps/extjstraining/components/dialogbasics/dialog
    2. Click Save All to save the changes.
    3. Copy the node: /apps/extjstraining/components/dialogbasics/singlepanel
    4. Paste the copied node below: /apps/extjstraining/components/dialogbasics
    5. Select the node: /apps/extjstraining/components/dialogbasics/Copy of singlepanel and rename it dialog.
  2. Edit the component: the dialog displays as follows:

    file

Example 3: Multi Panel Dialog

The Multi Panel dialog has the same display as the Full dialog but it is built differently. Its characteristics are:

  • Is defined by a node (node type = cq:Dialog, xtype = tabpanel).
  • Displays 3 tabs (node type = cq:Panel).
  • Each tab has 2 textfields (node type = cq:Widget, xtype = textfield).
  • Is defined by the node:
    /apps/extjstraining/components/dialogbasics/multipanel
  • Is rendered in json format by requesting:
    http://localhost:4502/apps/extjstraining/components/dialogbasics/multipanel.-1.json
  • One advantage over the Full Dialog is that it has a simplified structure.
  • Recommended use: for multi-tab dialogs.

To use the Multi Panel dialog:

  1. Replace the dialog of the Dialog Basics component with the Multi Panel dialog:
    follow the steps described for the Example 2: Single Panel Dialog

  2. Edit the component: the dialog displays as follows:

    file

Example 4: Rich Dialog

The Rich dialog displays a window with two tabs. The first tab has a text field, a drop-down menu and a collapsible textarea. The second tab has a field set with four text fields and a collapsible field set with two text fields. Its characteristics are:

  • Is defined by a node (node type = cq:Dialog, xtype = dialog).
  • Displays 2 tabs (node type = cq:Panel).
  • The first tab has a dialogfieldset widget with a textfield and a selection widget with 3 options, and a collapsible dialogfieldset with a textarea widget.
  • The second tab has a dialogfieldset widget with 4 textfield widgets, and a collapsible dialogfieldset with 2 textfield widgets.
  • Is defined by the node:
    /apps/extjstraining/components/dialogbasics/rich
  • Is rendered in json format by requesting:
    http://localhost:4502/apps/extjstraining/components/dialogbasics/rich.-1.json

To use the Rich dialog:

  1. Replace the dialog of the Dialog Basics component with the Rich dialog:
    follow the steps described for the Example 2: Single Panel Dialog

  2. Edit the component: the dialog displays as follows:

    file

Dynamic Dialogs

The second component of the Using ExtJS Widgets group in the Sidekick is called 2. Dynamic Dialogs and includes three dynamic dialogs that are built with out-of-the-box widgets and with customized javascript logic. The dialogs are stored below /apps/extjstraining/components/dynamicdialogs. The dynamic dialogs are:

  • the Switch Tabs dialog (switchtabs node): it displays a window with two tabs. The first tab has a radio selection with three options: when an option is selected, a tab that relates to the option is displayed. The second tab has two text fields.
  • the Arbitrary dialog (arbitrary node): it displays a window with one tab. The tab has a field to drop or upload an asset and a field that displays some information about the containing page and about the asset if one is referenced.
  • the Toggle Fields dialog (togglefield node): it displays a window with one tab. The tab has a checkbox: when it is checked a field set with two text fields is displayed.

To include the 2. Dynamic Dialogs component on the sample page:

  1. Add the 2. Dynamic Dialogs component to the sample page from the Using ExtJS Widgets tab in the Sidekick.
  2. The component displays a title, some text and a PROPERTIES link: click to display the properties of the paragraph stored in the repository. Click again to hide the properties.

The component displays as follows:

file

Example 1: Switch Tabs Dialog

The Switch Tabs dialog displays a window with two tabs. The first tab has a radio selection with three options: when an option is selected, a tab that relates to the option is displayed. The second tab has two text fields.

Its main characteristics are:

  • Is defined by a node (node type = cq:Dialog, xtype = dialog).
  • Displays 2 tabs (node type = cq:Panel): 1 selection tab, the 2nd tab depends on the selection in the 1st tab (3 options).
  • Has 3 optional tabs (node type = cq:Panel), each one has 2 textfields (node type = cq:Widget, xtype = textfield). Only one optional tab is displayed at a time.
  • Is defined by the switchtabs node at:
    /apps/extjstraining/components/dynamicdialogs/switchtabs
  • Is rendered in json format by requesting:
    http://localhost:4502/apps/extjstraining/components/dynamicdialogs/switchtabs.-1.json

The logic is implemented through event listeners and javascript code as follows:

  • The dialog node has a "beforeshow" listener that hides all the optional tabs before the dialog is shown:
    beforeshow="function(dialog){Ejst.x2.manageTabs(dialog.items.get(0));}"
     dialog.items.get(0) gets the tabpanel that contains the selection panel and the 3 optional panels.
  • The Ejst.x2 object is defined in the exercises.js file at:
    /apps/extjstraining/clientlib/js/exercises.js
  • In the Ejst.x2.manageTabs() method, as the value of index is -1, all the optional tabs are hidden (i goes from 1 to 3).
  • The selection tab has 2 listeners: one that shows the selected tab when the dialog is loaded ("loadcontent" event) and one that shows the selected tab when the selection is changed ("selectionchanged" event):
    loadcontent="function(field,rec,path){Ejst.x2.showTab(field);}"
     selectionchanged="function(field,value){Ejst.x2.showTab(field);}"
  • In the Ejst.x2.showTab() method:
    field.findParentByType('tabpanel') gets the tabpanel that contains all the tabs (field represents the selection widget)
    field.getValue() gets the value of the selection, e.g.: tab2
    Ejst.x2.manageTabs() displays the selected tab.
  • Each optional tab has a listener that hides the tab on "render" event:
    render="function(tab){Ejst.x2.hideTab(tab);}"
  • In the Ejst.x2.hideTab() method:
    tabPanel is the tabpanel that contains all the tabs
    index is the index of the optional tab
    tabPanel.hideTabStripItem(index) hides the tab

It displays as follows:

file

Example 2: Arbitrary Dialog

Very often a dialog displays content from the underlying component.  The dialog described here, called Arbitrary dialog, pulls content from a different component.

The Arbitrary dialog displays a window with one tab. The tab has two fields: one to drop or upload an asset and one that displays some information about the containing page and about the asset if one has been referenced.

Its main characteristics are:

  • Is defined by a node (node type = cq:Dialog, xtype = dialog).
  • Displays 1 tabpanel widget (node type = cq:Widget, xtype = tabpanel) with 1 panel (node type = cq:Panel)
  • The panel has a smartfile widget (node type = cq:Widget, xtype = smartfile) and an ownerdraw widget (node type = cq:Widget, xtype = ownerdraw)
  • Is defined by the arbitrary node at:
    /apps/extjstraining/components/dynamicdialogs/arbitrary
  • Is rendered in json format by requesting:
    http://localhost:4502/apps/extjstraining/components/dynamicdialogs/arbitrary.-1.json

The logic is implemented through event listeners and javascript code as follows:

  • The ownerdraw widget has a "loadcontent" listener that shows info about the page containing the component and the asset referenced by the smartfile widget when the content is loaded:
    loadcontent="function(field,rec,path){Ejst.x2.showInfo(field,rec,path);}"
     field is set with the ownerdraw object
    path is set with the content path of the component (e.g.: /content/geometrixx/en/products/triangle/ui-tutorial/jcr:content/par/dynamicdialogs)
  • The Ejst.x2 object is defined in the exercises.js file at:
    /apps/extjstraining/clientlib/js/exercises.js
  • In the Ejst.x2.showInfo() method:
    pagePath is the path of the page containing the component
    pageInfo represents the page properties in json format
    reference is the path of the referenced asset
    metadata represents the metadata of the asset in json format
    ownerdraw.getEl().update(html);  displays the created html in the dialog

To use the Arbitrary dialog:

  1. Replace the dialog of the Dynamic Dialog component with the Arbitrary dialog:
    follow the steps described for the Example 2: Single Panel Dialog

  2. Edit the component: the dialog displays as follows:

    file

Example 3: Toggle Fields Dialog

The Toggle Fields dialog displays a window with one tab. The tab has a checkbox: when it is checked a field set with two text fields is displayed.

Its main characteristics are:

  • Is defined by a node (node type = cq:Dialog, xtype = dialog).
  • Displays 1 tabpanel widget (node type = cq:Widget, xtype = tabpanel) with 1 panel (node type = cq:Panel).
  • The panel has a selection/checkbox widget (node type = cq:Widget, xtype = selection, type = checkbox) and a collapsible dialogfieldset widget (node type = cq:Widget, xtype = dialogfieldset) that is hidden by default, with 2 textfield widgets (node type = cq:Widget, xtype = textfield).
  • Is defined by the togglefields node at:
    /apps/extjstraining/components/dynamicdialogs/togglefields
  • Is rendered in json format by requesting:
    http://localhost:4502/apps/extjstraining/components/dynamicdialogs/togglefields.-1.json

The logic is implemented through event listeners and javascript code as follows:

  • the selection tab has 2 listeners: one that shows the dialogfieldset when the content is loaded ("loadcontent" event) and one that shows the dialogfieldset when the selection is changed ("selectionchanged" event):
    loadcontent="function(field,rec,path){Ejst.x2.toggleFieldSet(field);}"
     selectionchanged="function(field,value){Ejst.x2.toggleFieldSet(field);}"
  • The Ejst.x2 object is defined in the exercises.js file at:
    /apps/extjstraining/clientlib/js/exercises.js
  • In the Ejst.x2.toggleFieldSet() method:
    box is the selection object
    panel is the panel containing the selection and the dialogfieldset widgets
    fieldSet is the dialogfieldset object
    show is the value of the selection (true or false)
    based on 'show' the dialogfieldset is displayed or not

To use the Toggle Fields dialog:

  1. Replace the dialog of the Dynamic Dialog component with the Toggle Fields dialog:
    follow the steps described for the Example 2: Single Panel Dialog
  2. Edit the component: the dialog displays as follows:
  1. Replace the dialog of the Dynamic Dialog component with the Toggle Fields dialog:
    follow the steps described for the Example 2: Single Panel Dialog

  2. Edit the component: the dialog displays as follows:

    file

Custom Widgets

The out-of-the-box widgets shipped with AEM should cover most use cases. However it might be sometimes necessary to create a custom widget to cover a project-specific requirement. Custom widgets can be created by extending existing ones. To help you get started with such customization, the Using ExtJS Widgets package includes three dialogs that use three different custom widgets:

  • the Multi Field dialog (multifield node) displays a window with one tab. The tab has a customized multifield widget that has two fields: a drop-down menu with two options and a text field. As it is based on the out-of-the-box multifield widget (that only has a text field), it has all the features of the multifield widget.
  • the Tree Browse dialog (treebrowse node) displays a window with one tab containing a path browse widget: when you click the arrow, a window opens up in which you can browse a hierarchy and select an item. The path of the item is then added to the path field and is persisted when the dialog is closed.
  • a Rich Text Editor Plug-in based dialog (rteplugin node) that adds a custom button to the Rich Text Editor to insert some custom text to the main text. It consists of a richtext widget (RTE) and of a custom feature which is added through the RTE plug-in mechanism.

The custom widgets and the plugin are included in the component called 3. Custom Widgets of the Using ExtJS Widgets package. To include this component to the sample page:

  1. Add the 3. Custom Widgets component to the sample page from the Using ExtJS Widgets tab in the Sidekick.
  2. The component displays a title, some text and, when clicking the PROPERTIES link, the properties of the paragraph stored in the repository. Clicking again hides the properties.
    The component displays as follows:
file

Example 1: Custom Multifield Widget

The Custom Multifield widget based dialog displays a window with one tab. The tab has a customized multifield widget that, unlike the standard one which has one field, has two fields: a drop-down menu with two options and a text field.

The Custom Multifield widget based dialog:

  • Is defined by a node (node type = cq:Dialog, xtype = dialog).
  • Displays 1 tabpanel widget (node type = cq:Widget, xtype = tabpanel) containing a panel (node type = cq:Widget, xtype = panel).
  • The panel has a multifield widget (node type = cq:Widget, xtype = multifield).
  • The multifield widget has a fieldconfig (node type = nt:unstructured, xtype = ejstcustom, optionsProvider = Ejst.x3.provideOptions) that is based on the custom xtype 'ejstcustom':
    • 'fieldconfig' is a config option of the CQ.form.MultiField object.
    • 'optionsProvider' is a configuration of the ejstcustom widget. It is set with the Ejst.x3.provideOptions method which is defined in exercises.js at:
      /apps/extjstraining/clientlib/js/exercises.js
      and returns 2 options.
  • Is defined by the multifield node at:
    /apps/extjstraining/components/customwidgets/multifield
  • Is rendered in json format by requesting:
    http://localhost:4502/apps/extjstraining/components/customwidgets/multifield.-1.json

The custom multifield widget (xtype = ejstcustom):

  • Is a javascript object called Ejst.CustomWidget.
  • Is defined in the CustomWidget.js javascript file at:
    /apps/extjstraining/clientlib/js/CustomWidget.js
  • Extends the CQ.form.CompositeField widget.
  • Has 3 fields: hiddenField (Textfield), allowField (ComboBox) and otherField (Textfield)
  • Overrides CQ.Ext.Component#initComponent to add the 3 fields:
    • hiddenField is a CQ.Ext.form.Hidden object
    • allowField is a CQ.form.Selection object of type 'select'. optionsProvider is a configuration of the Selection object that is instantiated with the optionsProvider  configuration of the CustomWidget defined in the dialog
    • otherField is a CQ.Ext.form.TextField object
  • Overrides the methods setValue, getValue and getRawValue of CQ.form.CompositeField in order to set and retrieve the value of CustomWidget with the format:
    <allowField value>/<otherField value>, e.g.: 'Bla1/hello'.
  • Registers itself as 'ejstcustom' xtype:
    CQ.Ext.reg('ejstcustom', Ejst.CustomWidget);

The Custom Multifield widget based dialog displays as follows:

file

Example 2: Custom Treebrowse Widget

The custom Treebrowse widget based dialog displays a window with one tab containing a custom path browse widget: when you click the arrow, a window opens up in which you can browse a hierarchy and select an item. The path of the item is then added to the path field and is persisted when the dialog is closed.

 

The custom treebrowse dialog:

  • Is defined by a node (node type = cq:Dialog, xtype = dialog).
  • Displays 1 tabpanel widget (node type = cq:Widget, xtype = tabpanel) containing a panel (node type = cq:Widget, xtype = panel).
  • The panel has a custom widget (node type = cq:Widget, xtype = ejstbrowse)
  • Is defined by the treebrowse node at:
    /apps/extjstraining/components/customwidgets/treebrowse
  • Is rendered in json format by requesting:
    http://localhost:4502/apps/extjstraining/components/customwidgets/treebrowse.-1.json

The custom treebrowse widget (xtype = ejstbrowse):

  • Is a javascript object called Ejst.CustomWidget.
  • Is defined in the CustomBrowseField.js javascript file at:
    /apps/extjstraining/clientlib/js/CustomBrowseField.js
  • Extends CQ.Ext.form.TriggerField.
  • Defines a browse window called browseWindow.
  • Overrides CQ.Ext.form.TriggerField#onTriggerClick to show the browse window when the arrow is clicked.
  • Defines a CQ.Ext.tree.TreePanel object:
    • It gets its data by calling the servlet registered at /bin/wcm/siteadmin/tree.json.
    • Its root is "apps/extjstraining".
  • Defines a window object (CQ.Ext.Window):
    • Based on the pre-defined panel.
    • Has an OK button that sets the value of the selected path and hides the panel.
  • The window is anchored below the Path field.
  • The selected path is passed from the browse field to the window on show event.
  • Registers itself as 'ejstbrowse' xtype:
    CQ.Ext.reg('ejstbrowse', Ejst.CustomBrowseField);

To use the Custom Treebrowse widget based dialog:

  1. Replace the dialog of the Custom Widgets component with the Custom Treebrowse dialog:
    follow the steps described for the Example 2: Single Panel Dialog

  2. Edit the component: the dialog displays as follows:

    file

Example 3: Rich Text Editor (RTE) Plug-in

The Rich Text Editor (RTE) Plug-in based dialog is a Rich Text Editor based dialog that has a custom button to insert some custom text within square brackets. The custom text can be parsed by some server-side logic (not implemented in this example), for example to add some text that is defined at the given path:

The RTE plugin based dialog:

  • Is defined by the rteplugin node at:
    /apps/extjstraining/components/customwidgets/rteplugin
  • Is rendered in json format by requesting:
    http://localhost:4502/apps/extjstraining/components/customwidgets/rteplugin.-1.json
  • The rtePlugins node has a child node inserttext (node type = nt:unstructured) that is named after the plugin. It has a property called features, that defines which of the plugin features are available to the RTE.

The RTE plugin:

  • Is a javascript object called Ejst.InsertTextPlugin.
  • Is defined in the InsertTextPlugin.js javascript file at:
    /apps/extjstraining/clientlib/js/InsertTextPlugin.js
  • Extends the CQ.form.rte.plugins.Plugin object.
  • The following methods define the CQ.form.rte.plugins.Plugin object and are overridden in the implementing plugin:
    • getFeatures() returns an array of all the features that the plugin makes available.
    • initializeUI() adds the new button to the RTE toolbar.
    • notifyPluginConfig() displays title and text when the button is hovered.
    • execute() is called when the button is clicked and performs the plugin action: it displays a window that is used to define the text to be included.
  • insertText() inserts a text using the corresponding dialog object Ejst.InsertTextPlugin.Dialog (see afterwards).
  • executeInsertText() is called by the apply() method of the dialog, which is triggered when the OK button is clicked.
  • Registers itself as 'inserttext' plugin:
    CQ.form.rte.plugins.PluginRegistry.register("inserttext", Ejst.InsertTextPlugin);
  • the Ejst.InsertTextPlugin.Dialog object defines the dialog that is opened when the plugin button is clicked. The dialog consists of a panel, a form, a textfield and 2 buttons (OK and Cancel).

To use the Rich Text Editor (RTE) Plug-in based dialog:

  1. Replace the dialog of the Custom Widgets component with the Rich Text Editor (RTE) Plug-in based dialog:
    follow the steps described for the Example 2: Single Panel Dialog
  2. Edit the component.
  3. Click the the last icon on the right (the one with four arrows). Enter a path and click OK:
    The path is displayed within brackets ([ ]).
  4. Click OK to close the Rich Text Editor.

The Rich Text Editor (RTE) Plug-in based dialog displays as follows:

file

Note

This example only shows how to implement the client-side part of the logic: the placeholders ([text]) have then to be parsed on the server-side explicitly (e.g. in the component JSP).

Tree Overview

The out-of-the-box CQ.Ext.tree.TreePanel object provides tree-structured UI representation of tree-structured data. The Tree Overview component included in the Using ExtJS Widgets package shows how to use the TreePanel object to display a JCR tree below a given path. The window itself can be docked/undocked. In this example, the window logic is embedded in the component jsp between <script></script> tags.

To include the Tree Overview component to the sample page:

  1. Add the 4. Tree Overview component to the sample page from the Using ExtJS Widgets tab in the Sidekick.
  2. The component displays:
    • a title, with some text
    • a PROPERTIES link: click to display the properties of the paragraph stored in the repository. Click again to hide the properties.
    • a floating window with a tree representation of the repository, that can be expanded.

The component displays as follows:

file

The Tree Overview component:

  • Is defined at:
    /apps/extjstraining/components/treeoverview
  • Its dialog enables to set the size of the window and to dock/undock the window (see details below).

The component jsp:

  • Retrieves the width, heigth and docked properties from the repository.
  • Displays some text about the tree overview data format.
  • Embeds the window logic in the component jsp between javascript tags.
  • Is defined at:
    apps/extjstraining/components/treeoverview/content.jsp

The javascript code embedded in the component jsp:

  • Defines a tree object by trying to retrieve a tree window from the page.
  • If the window displaying the tree does not exist, treePanel (CQ.Ext.tree.TreePanel) is created:
    • treePanel contains the data that is used to create the window.
    • The data are retrieved by calling the servlet registered at:
      /bin/wcm/siteadmin/tree.json
  • The beforeload listener makes sure the clicked node is loaded.
  • The root object sets the path apps/extjstraining as the tree root.
  • tree (CQ.Ext.Window) is set based on the pre-defined treePanel, and is displayed with:
    tree.show();
  • If the window already exists, it is displayed based on the width, heigth and docked properties retrieved from the repository.

The component dialog:

  • Displays 1 tab with 2 fields to set the size (width and heigth) of the tree overview window and 1 field to dock/undock the window
  • Is defined by a node (node type = cq:Dialog, xtype = panel).
  • The panel has a sizefield widget (node type = cq:Widget, xtype = sizefield) and a selection widget (node type = cq:Widget, xtype = selection, type = radio) with 2 options (true/false)
  • Is defined by the dialog node at:
    /apps/extjstraining/components/treeoverview/dialog
  • Is rendered in json format by requesting:
    http://localhost:4502/apps/extjstraining/components/treeoverview/dialog.-1.json
  • Displays as follows:
file

Grid Overview

A Grid Panel represents data in a tabular format of rows and columns. It is composed of the following:

  • Store : the model holding the data records (rows).
  • Column model : the column makeup.
  • View : encapsulates the user interface.
  • Selection model : the selection behavior.

The Grid Overview component included in the Using ExtJS Widgets package shows how to display data in a tabular format:

  • The example 1 uses static data.
  • The example 2 uses data retrieved from the repository.

To include the Grid Overview component to the sample page:

  1. Add the 5. Grid Overview component to the sample page from the Using ExtJS Widgets tab in the Sidekick.
  2. The component displays:
    •  a title with some text
    • a PROPERTIES link: click to display the properties of the paragraph stored in the repository. Click again to hide the properties.
    • a floating window containing data in tabular format.

The component displays as follows:

file

Example 1: Default Grid

In its out-of-the-box version, the Grid Overview component displays a window with static data in a tabular format. In this example, the logic is embedded in the component jsp in two ways:

  • the generic logic is defined between <script></script> tags
  • the specific logic is available in a separate .js file and is linked to in the jsp. This setup enables to easily switch between the two logic (static/dynamic) by commenting the desired <script> tags.

The Grid Overview component:

  • Is defined at:
    /apps/extjstraining/components/gridoverview
  • Its dialog enables to set the size of the window and to dock/undock the window.

The component jsp:

  • Retrieves the width, heigth and docked properties from the repository.
  • Displays some text as introduction to the grid overview data format.
  • References javascript code that defines the GridPanel object:
    <script type="text/javascript" src="/apps/extjstraining/components/gridoverview/defaultgrid.js"></script>
     defaultgrid.js defines some static data as a base for the GridPanel object.
  • Embeds javascript code between javascript tags that defines the Window object consuming the GridPanel object.
  • Is defined at:
    apps/extjstraining/components/gridoverview/content.jsp

The javascript code embedded in the component jsp:

  • Defines the grid object by trying to retrieve the window component from the page:
    var grid = CQ.Ext.getCmp("<%= node.getName() %>-grid");
  • If grid does not exist, a CQ.Ext.grid.GridPanel object (gridPanel) is defined by calling the getGridPanel() method (see below). This method is defined in defaultgrid.js.
  • grid is a CQ.Ext.Window object, based on the pre-defined GridPanel, and is displayed: grid.show();
  • If grid already exists, it is displayed based on the width, heigth and docked properties retrieved from the repository.

The javascript file (defaultgrid.js) referenced in the component jsp defines the getGridPanel() method which is called by the script embedded in the JSP and returns a CQ.Ext.grid.GridPanel object, based on static data. The logic is as follows:

  • myData is an array of static data formatted as a table of 5 columns and 4 rows.
  • store is a CQ.Ext.data.Store object that consumes myData.
  • store is loaded in memory:
    store.load();
  • gridPanel is a CQ.Ext.grid.GridPanel object that consumes store:
    •  the column widths are re-proportioned at all times:
      forceFit: true
    • only one row at a time can be selected:
      singleSelect:true

Example 2: Reference Search Grid

When you install the package, the content.jsp of the Grid Overview component displays a grid that is based on static data. It is possible to modify the component to display a grid with the following characteristics:

  • Has three columns.
  • Is based on data retrieved from the repository by calling a servlet.
  • The cells of the last column can be edited. The value is persisted in a test property below the node defined by the path displayed in the first column.

As explained in the section before, the window object gets its CQ.Ext.grid.GridPanel object by calling the getGridPanel() method defined in the defaultgrid.js file at /apps/extjstraining/components/gridoverview/defaultgrid.js. The Grid Overview component provides a different implementation for the getGridPanel() method, defined in the referencesearch.js file at /apps/extjstraining/components/gridoverview/referencesearch.js. By switching the .js file that is referenced in the component jsp, the grid will be based on data retrieved from the repository.

Switch the .js file that is referenced in the component jsp:

  1. In CRXDE Lite, in the content.jsp file of the component, comment the line that includes the defaultgrid.js file, so that it looks as follows:
    <!-- script type="text/javascript" src="/apps/extjstraining/components/gridoverview/defaultgrid.js"></script-->
  2. Remove the comment from the line that includes the referencesearch.js file, so that it looks as follows:
    <script type="text/javascript" src="/apps/extjstraining/components/gridoverview/referencesearch.js"></script>
  3. Save the changes.
  4. Refresh the sample page.

The component displays as follows:

file

The javascript code referenced in the component jsp (referencesearch.js) defines the getGridPanel() method called from the component jsp and returns a CQ.Ext.grid.GridPanel object, based on data that are dynamically retrieved from the repository. The logic in referencesearch.js defines some dynamic data as a base for the GridPanel:

  • reader is a CQ.Ext.data.JsonReader object that reads the servlet response in json format for 3 columns.
  • cm is a CQ.Ext.grid.ColumnModel object for 3 columns.
    The "Test" column cells can be edited as they are defined with an editor:
    editor: new CQ.Ext.form.TextField({})
  • the columns are sortable:
    cm.defaultSortable = true;
  • store is a CQ.Ext.data.GroupingStore object:
    • it gets its data by calling the servlet registered at "/bin/querybuilder.json" with a few parameters used to filter the query
    • it is based on reader, defined beforehand
    • the table is sorted according to the 'jcr:path' column in ascending order
  • gridPanel is a CQ.Ext.grid.EditorGridPanel object that can be edited:
    • it is based on the pre-defined store and on the column model cm
    • only one row at a time can be selected:
      sm: new CQ.Ext.grid.RowSelectionModel({singleSelect:true})
    • the afteredit listener makes sure that after a cell in the "Test" column has been edited:
      • the property 'test' of the node at the path defined by the "jcr:path" column is set in the repository with the value of the cell
      • if the POST is successful, the value is added to the store object, otherwise it is rejected

Your comments are welcome!
Did you notice a way we could improve the documentation on this page?
Please leave your comments below and we will make the appropriate changes.

COMMENTS

  • By Gaurav Singh - 8:40 AM on Feb 19, 2013   Reply
    Hi, I tried creating a customize-widget.js file and use it as xtype for my node(xtype: multifield) --> editConfig( xtype: customize-widget). All i want is on click of plus(+) sign, a text and a smart-image should add up so that i can give a title and drag-drop an image related to it.


    • By ppiegaze - 3:37 PM on Feb 26, 2013   Reply
      If you have more detailed info about your probem I suggest you try the forum:http://forums.adobe.com/community/digital_marketing_suite/cq5
    • By SANJAY - 4:37 PM on Mar 11, 2013   Reply
      Hi i have created a customize-widget.js for multi-component of Richtext and Image but the OK button of dialog is not clickable. Can anyone help.
      • By alvawb - 6:15 PM on Mar 11, 2013   Reply
        Might I suggest you post your question to our dedicated AEM forum at http://forums.adobe.com/community/digital_marketing_suite/cq5
      • By Runal - 5:43 PM on Apr 09, 2013   Reply
        Do we have ready packages available for all the samples dialog and widgets discussed on page?
        • By zumbrunn - 6:52 AM on Apr 11, 2013   Reply
          Hi Runal, no, we currently do not, although I can certainly see how that could be helpful and we will make a point to include more packages with the resulting sample code in the updated tutorials.
        • By Hari - 1:24 PM on Jul 10, 2013   Reply
          If we use dynamic dialogue in our project the index of the tabs is starting from 0 where is in given example it is starting from 1 which is giving incorrect tab
          • By Guillaume Carlino - 3:52 PM on Jul 11, 2013   Reply
            Hi Hari

            I tested it and the index of the tabs is starting from 1. I suggest that you post all details (what you're trying to achieve, what you've implemented/configured so far, any log output) to our dedicated forum: http://forums.adobe.com/community/digital_marketing_suite/cq5.
            You will reach a wider audience and receive a greater response.

            Hope that helps
            Guillaume
          • By Daniel Weber - 6:20 PM on Jul 23, 2013   Reply
            It would be nice if there were some walkthroughs/tutorials on some of these components! I am looking at building a custom multifield widget...
            • By Scott Brodersen - 2:10 PM on Jul 24, 2013   Reply
              Daniel, I will log your request. In the meantime, have you searched the Adobe CQ forum? There are a few threads on this topic, such as http://forums.adobe.com/thread/979400

              scott
            • By CQ tester - 12:57 PM on Sep 25, 2013   Reply
              How to recreate Example 1: Custom Multifield Widget with 2 selectboxes (instead of 1 selectbox and one textfield) and everyone of them loads data from json?
              • By Rahul - 10:04 AM on Oct 10, 2013   Reply
                I have a multifield in a widget js as :
                this.linkPathField= new CQ.form.MultiField({
                predicate: "siteadmin",
                showTitlesInTree: true,
                allowBlank: true,
                width: 335,
                fieldLabel : "Footer Links :",
                fieldDescription : "Click the '+' to add a new navigation link for this section",
                addItemLabel : "Add New Link",
                listeners: {
                change: {
                scope:this,
                fn:this.updateHidden
                },
                dialogclose : {
                scope:this,
                fn:this.updateHidden
                }
                }
                });

                When this multifield appears in the dialog, and i click on add item, i am getting plain text fields. I want pathfields to appear. What can I do to have pathFields in my Multifield???

                Thanks in advance.
                • By docs team - 3:58 PM on Oct 10, 2013   Reply
                  For programming questions, please post on the forums:
                  http://forums.adobe.com/community/digital_marketing_suite/cq5
                • By Frustrated CQ5 Developer - 7:42 PM on Oct 16, 2013   Reply
                  Why is all the documentation almost impossible to understand for a CQ5 beginner and why is nobody pointing them out?

                  Don't get me wrong, I fully recognize the powerful and rich features CQ5 brings, but it seems to have one of the WORST documentation, especially for beginners!
                  • By aheimoz - 4:46 AM on Oct 17, 2013   Reply
                    Thanks for your feedback - although we are very sorry to hear that you're finding the documentation difficult to work with.

                    I'll register an issue on the fact that we need to improve the documentation for new developers - if you have any specific issues just let us know.

                    In the meantime, just in case you haven't seen the following resources, they might help (apologies if you are already aware of them all):
                    - we have a getting started page for developers
                    http://dev.day.com/docs/en/cq/current/getting_started/first_steps_for_developers.html
                    - you can ask questions on our forum:
                    http://help-forums.adobe.com/content/adobeforums/en/experience-manager-forum/adobe-experience-manager.html
                    - there are many other articles on a range of issues:
                    http://helpx.adobe.com/marketing-cloud/experience-manager.html

                    Hope that helps, and feel free to contact us at any time.
                    • By Anonymous - 3:31 PM on Oct 17, 2013   Reply
                      Hi aheimoz

                      I really appreciate your prompt reply, guess I was just frustrated with a non-working custom xtype definition with multiField, still having trouble as of now, perhaps you could provide some help!

                      GOAL
                      ---------------------------------------
                      I want to create a custom xtype consists of a textfield and a textarea
                      I want to be able to add multiple of these from the component dialog via multiField


                      STEP 1
                      ---------------------------------------
                      I created a custom component called [custom-accordion]
                      /apps/myprojects/components/custom-accordion/custom-accordion.jsp


                      STEP 2a
                      ---------------------------------------
                      I've defined a custom xtype called accordion-item.js, structure as follows:
                      /apps
                      - /myproject
                      -- /clientlib { primaryType: ClientLibraryFolder, dependencies: [cq.widgets], categories: [apps.myproject.customwidgets], sling:resourceType: [widgets/clientlib] }
                      ---- js.txt
                      ---- /js
                      ------ accordion-item.js

                      STEP 2b
                      ---------------------------------------
                      I followed every steps described in the reply here:
                      http://forums.adobe.com/message/4332833

                      copy/pasted content from the post to accordion-item.js
                      registered the xtype with this line:
                      CQ.Ext.reg('accordionitem', CQ.AcordionItemWidget);

                      Content for js.txt
                      #base=js
                      accordion-item.js

                      STEP 2c
                      ---------------------------------------
                      I've added nodes in dialog with this structure:
                      - dialog
                      -- items { primaryType: cq:TabPanel }
                      ---- items { primaryType: cq:WidgetCollection }
                      ------ tab1 { primaryType: cq:Panel }
                      -------- accordion-item { primaryType: cq:Widget, xtype: multifield }
                      ---------- fieldConfig { primaryType: nt:unstructured, xtype: accordionitem }


                      STEP 3
                      ---------------------------------------
                      I've included the custom xtype js definition in my component JSP file like this
                      <cq:includeClientLib js="apps.lcbo.customwidgets"/>


                      ERROR
                      ---------------------------------------
                      When I run the page with the component in authoring mode, I see the multiField and it's "Add Item" option, but when I click on "Add Item" I get a JS error
                      "Uncaught cannot create Component: xtype 'accordionitem' not found and no default supplied "

                      Also this 404:
                      GET http://localhost:4502/apps/myproject/clientlib.js 404 (Not Found)

                      Why is the clientlib.js not found when I clearly included it in my component?
                      • By aheimoz - 9:50 AM on Oct 18, 2013   Reply
                        This level of question really would be better suited to the forum:
                        - http://help-forums.adobe.com/content/adobeforums/en/experience-manager-forum/adobe-experience-manager.html
                        You will reach a wider audience and receive a greater response.

                        Hope that helps.
                        • By Rohit - 7:46 PM on Jan 02, 2014   Reply
                          Hi,
                          I am getting exactly the same error message which you are getting. Did you got any solution for same.

                          "Uncaught cannot create Component: xtype 'accordionitem' not found and no default supplied "
                          • By Guillaume Carlino - 10:54 AM on Jan 06, 2014   Reply
                            Hi Rohit

                            As suggested by aheimoz, this question is really worth asking on the forum:
                            http://help-forums.adobe.com/content/adobeforums/en/experience-manager-forum/adobe-experience-manager.html
                            You will reach a wider audience and receive a greater response.

                            Hope that helps
                            Guillaume
                    • By Yash - 11:10 AM on Dec 25, 2013   Reply
                      Why is the sling:resourceType set to widgets/clientlib in this case. Wouldn't it work just by setting dependencies
                      • By Anonymous - 12:06 AM on Apr 10, 2014   Reply
                        You can add me to the list of people who've tried this: http://helpx.adobe.com/experience-manager/using/creating-custom-xtype.html and wasted my time since it doesn't work. I understand that mistakes happen, but the author of that article has been told about the useless article...it's been months, nothing is being done.

                        ADD A COMMENT

                         

                        In order to post a comment, you need to sign-in.

                        Note: Customers with DayCare user accounts need to create a new account for use on day.com.

                        ***